// utf8 的编码

#include "../include/zgl_language.hpp"

CZGLanguage::CZGLanguage(){}
CZGLanguage::~CZGLanguage(){}


bool CZGLanguage::retErrInfo(const char *errInfo)
{

    unsigned int iStrLen = strlen(errInfo) + 256;
    retStr = (char *)malloc(iStrLen);
    memset(retStr, 0x00, iStrLen);
    unsigned int iLineLen = pText - pLineHead;
    if( iLineLen > 110 )
    {
        iLineLen = 110;
        pLineHead = pText - 109;
    }

    char mLine[128];
    memset(mLine, 0x00, sizeof(mLine));
    memcpy(mLine, pLineHead, iLineLen);
    // sprintf(retStr, "!!! Syntax file ERROR !!!\n|1| Line %d : \"%s\"<<<\n", iLineNum, mLine);
    // sprintf(retStr, "%s|2| %s\n", retStr, errInfo);
    sprintf(retStr, "!!! Syntax file ERROR !!!\n|1| Line %d : \"%s\"<<<\n|2| %s\n", iLineNum, mLine, errInfo);

    printf("%s", retStr);

    return false;
}

bool CZGLanguage::retErrInfo4CodeFile(const char *errInfo)
{
    unsigned int iStrLen = strlen(errInfo) + 256;
    retStr = (char *)malloc(iStrLen);
    memset(retStr, 0x00, iStrLen);

    unsigned int iLineLen = pText - pLineHead;
    if( iLineLen > 110 )
    {
        iLineLen = 110;
        pLineHead = pText - 109;
    }

    char mLine[128];
    memset(mLine, 0x00, sizeof(mLine));
    memcpy(mLine, pLineHead, iLineLen);

    sprintf(retStr, "\n!!! Code file ERROR !!!\n|1| Line %d : \"%s\"<<<\n|2| %s\n", iLineNum, mLine, errInfo);
    // sprintf(retStr, "%s|2| %s\n", retStr, errInfo);

    printf("%s", retStr);

    return false;
}


bool CZGLanguage::retWarnInfo4CodeFile(const char *warnInfo)
{
    unsigned int iStrLen = strlen(warnInfo) + 256;
    retStr = (char *)malloc(iStrLen);
    memset(retStr, 0x00, iStrLen);

    unsigned int iLineLen = pText - pLineHead;
    if( iLineLen > 110 )
    {
        iLineLen = 110;
        pLineHead = pText - 109;
    }

    char mLine[128];
    memset(mLine, 0x00, sizeof(mLine));
    memcpy(mLine, pLineHead, iLineLen);

    sprintf(retStr, "\n!!! Code file WARNING !!!\n|1| Line %d : \"%s\"<<<\n|2| %s\n", iLineNum, mLine, warnInfo);

    printf("%s", retStr);

    return false;
}

unsigned long CZGLanguage::getFileSize(char *fileName)
{
    FILE *fp = fopen(fileName, "rb");
    if(fp == NULL)
        return 0;
    fseek(fp, 0L, SEEK_END);
    unsigned long iSize = ftell(fp);
    fclose(fp);
    return iSize;
}

/********************************************
unsigned int CZGLanguage::getSDBMHash(char *pStr)
{
    unsigned int iHash = 0;
    while (*pStr)
    {
        iHash = (*pStr++) + (iHash << 6) + (iHash << 16) - iHash;
    }
    return (iHash & 0x7FFFFFFF);
}
*********************************************/

// 是否字母或下划线
bool CZGLanguage::isLetter() 
{
    if(*pText > 96 && *pText < 123) {
        // *pText -= 32;
        return true;
    } else if(*pText > 64 && *pText < 91)
        return true;
    else if(*pText == '_')
        return true;
    else
        return false;
}

// 是否可命名字符
bool CZGLanguage::isName()
{
    if( isLetter() )
        return true;
    else if(*pText > 47 && *pText < 58) //0~9
        return true;
    else if(*pText < 0 ) // 支持中文
        return true;
    else
        return false;
}

// 截取字符串
bool CZGLanguage::getCmpStr()
{
    pLgStr = pText;
    iLgStrLen = 0;

    while( isName() )
    {
        pText ++ ;
        iLgStrLen ++ ;
    }

    if( iLgStrLen > MAX_STR_SZ )
        return retErrInfo("The string is too long.");

    return true;
}

// 截取正整数
bool CZGLanguage::getInt()
{
    pLgStr = pText;
    iLgStrLen = 0;

    while(*pText >= '0' && *pText <= '9' ) //0~9
    {
        pText ++ ;
        iLgStrLen ++ ;
    }

    return true;
}


// 是否可见字符，不包括空格符 
bool CZGLanguage::isVisible()
{
    if( *pText >= 33 && *pText <= 126 )
        return true;
    else if(*pText < 0 ) // 支持中文
        return true;
    else
        return false;
}

bool CZGLanguage::getVisibleStr()
{
    pLgStr = pText;
    unsigned int iCount = 0;

    while( isVisible() )
    {
        pText ++ ;
        iCount ++ ;
    }

/***********************************
    if( iCount > MAX_STR_SZ )
        return doWithError("The string is too long.");
***********************************/

    iLgStrLen = iCount;
    return true;
}

bool CZGLanguage::cmpStr(const char *pSrc, char *pTar, unsigned int iLen)
{
    if( isCaseSensitive )
        return strncmp(pSrc,pTar,iLen) == 0 ? true : false;

    for( ; iLen; iLen -- )
    {
        if( *pSrc == *pTar || (*pSrc >= 'a' && *pSrc <= 'z' && (*pSrc)-32 == *pTar) ) {
            pSrc ++ ;
            pTar ++ ;
        } else
            return false;
    }

    return true;
}

bool CZGLanguage::createNewStr()
{
    struct stStr *pStrNew = getStrNode();
    memset(pStrNew, 0x00, sizeof(struct stStr));

    pStrNew->pName = pLgStr;
    pStrNew->iNameLen = iLgStrLen;

    unsigned int iLen = 0;
    char mBuf[8];

    // 注释行
    // while( ! strncmp(pText, "__//__", 6) )
    while( true )
    {
		if( ! strncmp(pText, "__//__", 6) ) {
        	for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        	pText ++ ;  // pass \n , \0
        	iLineNum ++ ;
        	pLineHead = pText;
		} else if( ! strncmp(pText, "__/*__", 6) ) {
			pText += 6;
        	for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
				if( *pText == '\n' ) {
        			iLineNum ++ ;
        			pLineHead = pText;
				}
			}

			// 最后一整行也注释掉
        	for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        	pText ++ ;  // pass \n , \0
        	iLineNum ++ ;
        	pLineHead = pText;
		} else
			break ;
    }

    if( *pText != '<' )
    {
        pText ++ ;
        return retErrInfo("Miss '<' here !");
    }

    pText ++ ;   // pass <

    //////////////////////////////////////////////

    iLen = 0;
    for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

    if( ! iLen )
    {
        pText ++ ;
        return retErrInfo("Miss number here !");
    }

    if( iLen > 7 )
        return retErrInfo("Number is too big !");

    memset(mBuf, 0x00, sizeof(mBuf));
    strncpy(mBuf, pText-iLen, iLen);
    pStrNew->iMinLen = atoi(mBuf);

    if( pStrNew->iMinLen == 0 )
        return retErrInfo("Left number can not be 0 !");

// printf("pStrNew->iMinLen = [%d]\n", pStrNew->iMinLen);  // debug

    //////////////////////////////////////////////

    if( *pText != ',' )
    {
        pText ++ ;
        return retErrInfo("Miss , here !");
    }

    *pText ++ ;  // pass ,

    iLen = 0;
    for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

    if( ! iLen )
    {
        pText ++ ;
        return retErrInfo("Miss number here !");
    }

    if( iLen > 7 )
        return retErrInfo("Number is too big !");

    memset(mBuf, 0x00, sizeof(mBuf));
    strncpy(mBuf, pText-iLen, iLen);
    pStrNew->iMaxLen = atoi(mBuf);

// printf("pStrNew->iMaxLen = [%d]\n", pStrNew->iMaxLen);  // debug

    if( pStrNew->iMinLen > pStrNew->iMaxLen )
        return retErrInfo("Can not be : left number > right number !");

    if( *pText != '>' )
        return retErrInfo("Miss > here !");

    pText ++ ;    // pass >

    for( ; *pText == ' ' || *pText == '\t' || *pText == '\r'; pText ++ );
    if( *pText != '\n' && *pText != '\0' )
    {
        pText ++ ;
        return retErrInfo("Too many context !");
    }

    pText ++ ;    // pass \n \0

    iLineNum ++ ;
    pLineHead = pText;

    //////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////

    pStrNew->pstStrLevelList = getStrLevelNode();
    memset(pStrNew->pstStrLevelList, 0x00, sizeof(struct stStrLevel));
    struct stStrLevel *pStrLevelTail = pStrNew->pstStrLevelList;

    // 注释行
    // while( ! strncmp(pText, "__//__", 6) )
    while( true )
    {
        if( ! strncmp(pText, "__//__", 6) ) {
            for( ; *pText != '\n' && *pText != '\0'; pText ++ );
            pText ++ ;  // pass \n , \0

            iLineNum ++ ;
            pLineHead = pText;
        } else if( ! strncmp(pText, "__/*__", 6) ) {
			pText += 6;   // pass __/*__
            for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
                if( *pText == '\n' ) {
                    iLineNum ++ ;
                    pLineHead = pText;
                }
            }

            // 最后一整行也注释掉
            for( ; *pText != '\n' && *pText != '\0'; pText ++ );
            pText ++ ;  // pass \n , \0
            iLineNum ++ ;
            pLineHead = pText;
        } else
            break ;
    }

    if( *pText != '[' )
    {
        pText ++ ;
        return retErrInfo("Miss '[' here !");
    }

while( *pText != '\0' )
{
    if( ! strncmp(pText, "__//__", 6) ) {
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    } else if( ! strncmp(pText, "__/*__", 6) ) {
		pText += 6;   // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

		continue ;
    }

    pText ++ ;   // pass [

    //////////////////////////////////////////////

    iLen = 0;
    for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

    if( ! iLen )
    {
        pText ++ ;
        return retErrInfo("Miss number here !");
    }

    if( iLen > 7 )
        return retErrInfo("Number is too big !");

    memset(mBuf, 0x00, sizeof(mBuf));
    strncpy(mBuf, pText-iLen, iLen);
    pStrLevelTail->iMinLen = atoi(mBuf);

// printf("pStrLevelTail->iMinLen = [%d]\n", pStrLevelTail->iMinLen);  // debug

    //////////////////////////////////////////////
    
    if( *pText != ',' )
    {
        pText ++ ;
        return retErrInfo("Miss , here !");
    }

    *pText ++ ;  // pass ,

    iLen = 0;
    for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

    if( ! iLen )
    {
        pText ++ ;
        return retErrInfo("Miss number here !");
    }

    if( iLen > 7 )
        return retErrInfo("Number is too big !");

    memset(mBuf, 0x00, sizeof(mBuf));
    strncpy(mBuf, pText-iLen, iLen);
    pStrLevelTail->iMaxLen = atoi(mBuf);

// printf("pStrLevelTail->iMaxLen = [%d]\n", pStrLevelTail->iMaxLen);  // debug

    if( pStrLevelTail->iMinLen > pStrLevelTail->iMaxLen )
        return retErrInfo("Can not be : left number > right number !");

    if( *pText != ']' )
        return retErrInfo("Miss ] here !");

    pText ++ ;    // pass ]

    /////////////////////////////////////////////////////

    if( *pText==' ' || *pText=='\t' || *pText=='\n' || *pText=='\r' || *pText=='\0' )
    {
        pText ++ ;
        return retErrInfo("Miss content here !");
    }

    for( ; *pText != ' ' && *pText != '\t' && *pText != '\n' && *pText != '\r' && *pText != '\0'; pText ++ )
    {
        if( *pText == '?' && *(pText+1) == '?' ) {
            pStrLevelTail->mMap[128] = true;
            pText ++ ;
            continue ;
        } else if( *pText < 0 ) {
            return retErrInfo("Must be ascii code !");
        } else
            pStrLevelTail->mMap[*pText] = true;
    }

/******************************************************
 * debug
for(int i=0; i<sizeof(pStrLevelTail->mMap); i ++ )
{
    printf("%d : %d\n", i, pStrLevelTail->mMap[i]);
}
******************************************************/

    for( ; *pText == ' ' || *pText == '\t' || *pText == '\r'; pText ++ );
    if( *pText != '\n' && *pText != '\0' )
    {
        pText ++ ;
        return retErrInfo("Too many context !");
    }

    pText ++ ;    // pass \n \0
    iLineNum ++ ;
    pLineHead = pText;

    if( *pText != '[' || ! strncmp(pText,"[NO]",4) )
        break ;

    pStrLevelTail->next = getStrLevelNode();
    memset(pStrLevelTail->next, 0x00, sizeof(struct stStrLevel));
    pStrLevelTail = pStrLevelTail->next;

} // while( *pText != '\0' )

    pStrNew->next = pstStrList;
    pstStrList = pStrNew;

	// get [NO] key word
	if( ! strncmp(pText, "[NO]", 4) )
	{
		pText += 4; // pass [NO]

		while( true )
		{
			for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );
			if( *pText=='\n' || *pText=='\0' )
			{
				pText ++ ;
				iLineNum ++ ;
				pLineHead = pText;

				break ;
			}

			struct stString * pNewString = getStringNode();
			memset(pNewString, 0x00, sizeof(struct stString));
			pNewString->pStr = pText;
			pNewString->iStrLen = 0;
			for( ; *pText!=' ' && *pText!='\t' && *pText!='\r' && *pText!='\n'; pText ++ ) pNewString->iStrLen ++ ;

			pNewString->next = pStrNew->pNoKeyWord;
			pStrNew->pNoKeyWord = pNewString;
		}
	}
	
	pText -- ;   // 避免后续循环跳过当前 \n

    return true;
}

bool CZGLanguage::readDebugLimit()
{
	struct stString * pNewDebugLimit = NULL;

    for( ; *pText == ' ' || *pText == '\t' || *pText == '\r'; pText ++ );

while( *pText != '\0' )
{
    if( *pText == '\n' || *pText == '\0' )
    {
        pText ++ ;    // pass \n \0
        iLineNum ++ ;
        pLineHead = pText;
    }

    if( ! strncmp(pText, "__//__", 6) ) {
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    } else if( ! strncmp(pText, "__/*__", 6) ) {
		pText += 6;   // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }
// printStrForDebug("pText11111", pText, 10);

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

		continue ;
    }

// printStrForDebug("pText", pText, 10);

	if( *pText == '[' )
	{
		pNewDebugLimit = getStringNode();
		memset(pNewDebugLimit, 0x00, sizeof(struct stString));

    	pText ++ ;   // pass [
		for( ; *pText == ' ' || *pText == '\t'; pText ++ );

    	//////////////////////////////////////////////

    	if( ! getCmpStr() )
        	return false;

    	if( iLgStrLen == 0 )
        	return retErrInfo("Miss tree name here !");

    	pNewDebugLimit->pStr = pLgStr;
    	pNewDebugLimit->iStrLen = iLgStrLen;

// printStrForDebug("pNewDebugLimit Name", pNewDebugLimit->pStr, pNewDebugLimit->iStrLen);  // debug

    	//////////////////////////////////////////////
    
		for( ; *pText == ' ' || *pText == '\t'; pText ++ );
    	if( *pText != ',' )
    	{
        	pText ++ ;
        	return retErrInfo("Miss , here !");
    	}

    	*pText ++ ;  // pass ,
		for( ; *pText == ' ' || *pText == '\t'; pText ++ );

    	unsigned int iLen = 0;
    	for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

    	if( ! iLen )
    	{
        	pText ++ ;
        	return retErrInfo("Miss number here !");
    	}

    	if( iLen > 7 )
        	return retErrInfo("Number is too big !");

		char mBuf[8];
    	memset(mBuf, 0x00, sizeof(mBuf));
    	strncpy(mBuf, pText-iLen, iLen);
    	pNewDebugLimit->iNum = atoi(mBuf);

// printf("pNewDebugLimit Num : %d\n", pNewDebugLimit->iNum);   // debug

		for( ; *pText == ' ' || *pText == '\t'; pText ++ );
    	if( *pText != ']' )
        	return retErrInfo("Miss ] here !");

    	pText ++ ;    // pass ]
    	for( ; *pText == ' ' || *pText == '\t' || *pText == '\r'; pText ++ );

    	pNewDebugLimit->next = pstDebugLimit;
    	pstDebugLimit = pNewDebugLimit;
	}
    else if( *pText == '<' )
    {
        pNewDebugLimit = getStringNode();
        memset(pNewDebugLimit, 0x00, sizeof(struct stString));

        pText ++ ;   // pass <
        for( ; *pText == ' ' || *pText == '\t'; pText ++ );

        //////////////////////////////////////////////

        unsigned int iLen = 0;
        for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

        if( iLen > 7 )
            return retErrInfo("Number is too big !");

        char mBuf[8];
        memset(mBuf, 0x00, sizeof(mBuf));
        strncpy(mBuf, pText-iLen, iLen);
        pNewDebugLimit->iStrLen = atoi(mBuf);   // 最小行数

// printf("pNewDebugLimit Min LineNum : %d\n", pNewDebugLimit->iStrLen);   // debug

        //////////////////////////////////////////////

        for( ; *pText == ' ' || *pText == '\t'; pText ++ );
        if( *pText != ',' )
        {
            pText ++ ;
            return retErrInfo("Miss , here !");
        }

        *pText ++ ;  // pass ,
        for( ; *pText == ' ' || *pText == '\t'; pText ++ );

        iLen = 0;
        for( ; *pText >= '0' and *pText <='9'; pText ++ ) iLen ++ ;

        if( iLen > 7 )
            return retErrInfo("Number is too big !");

        memset(mBuf, 0x00, sizeof(mBuf));
        strncpy(mBuf, pText-iLen, iLen);
        pNewDebugLimit->iNum = atoi(mBuf);   // 最大行数

// printf("pNewDebugLimit Max LineNum : %d\n", pNewDebugLimit->iNum);   // debug

		if( pNewDebugLimit->iStrLen >= pNewDebugLimit->iNum )
            return retErrInfo("Min LineNum can not >= Max LineNum !");

        for( ; *pText == ' ' || *pText == '\t'; pText ++ );
        if( *pText != '>' )
            return retErrInfo("Miss > here !");

        pText ++ ;    // pass >
        for( ; *pText == ' ' || *pText == '\t' || *pText == '\r'; pText ++ );

        pNewDebugLimit->next = pstDebugLimit;
        pstDebugLimit = pNewDebugLimit;
	}
	else
		break ;

} // while( *pText != '\0' )

/************************************************
pNewDebugLimit = pstDebugLimit;
for( ; pNewDebugLimit; pNewDebugLimit=pNewDebugLimit->next )
{
	printStrForDebug("pNewDebugLimit Name", pNewDebugLimit->pStr, pNewDebugLimit->iStrLen);  // debug
	printf("pNewDebugLimit Num : %d\n", pNewDebugLimit->iNum);   // debug
}
/************************************************/

    return true;
}

// 创建一个自定义的属性组合，简化 @ 后的表达
bool CZGLanguage::createNewAttrGroup()
{
    struct stString * pAttrGroupNew = getStringNode();
    memset(pAttrGroupNew, 0x00, sizeof(struct stString));

    pAttrGroupNew->pStr = pLgStr;
    pAttrGroupNew->iStrLen = iLgStrLen;

while( *pText != '\0' )
{
    // 注释行
    if( ! strncmp(pText, "__//__", 6) ) {
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    } else if( ! strncmp(pText, "__/*__", 6) ) { 
		pText += 6;   // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }

	// 编译 和 转换 部分的属性标记值可能重复冲突，需要检查
    if( ! strncmp(pText, "STRING", 6)  ) {
		if( ATTR_STRING & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_STRING;
        pText += 6;

    } else if( ! strncmp(pText, "SKIP_INDENT", 11)  ) {
		if( ATTR_SKIP_INDENT & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_SKIP_INDENT;
        pText += 13;

    } else if( ! strncmp(pText, "CAN_SKIP", 8)  ) {
		if( ATTR_CAN_SKIP & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_CAN_SKIP;
        pText += 8;

    } else if( ! strncmp(pText, "NEXT_LINE", 9)  ) {
		if( ATTR_NEXT_LINE & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_NEXT_LINE;
        pText += 9;

    } else if( ! strncmp(pText, "NEXT_LINES", 10)  ) {
		if( ATTR_NEXT_LINES & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_NEXT_LINES;
        pText += 10;

    } else if( ! strncmp(pText, "EXPR", 4)  ) {
		if( ATTR_EXPR & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_EXPR;
        pText += 4;

    } else if( ! strncmp(pText, "NOT_EXPR_END", 12)  ) {
        if( ATTR_NOT_EXPR_END & pAttrGroupNew->iNum )
            return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_NOT_EXPR_END;
        pText += 12;

    } else if( ! strncmp(pText, "IF_SOME_WITH_UP", 15)  ) {
		if( ATTR_IF_SOME_WITH_UP & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_IF_SOME_WITH_UP;
        pText += 15;

    } else if( ! strncmp(pText, "IF_NOT_SOME_WITH_UP", 19)  ) {
		if( ATTR_IF_NOT_SOME_WITH_UP & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_IF_NOT_SOME_WITH_UP;
        pText += 19;

    } else if( ! strncmp(pText, "IF_SOME_WITH_DOWN", 17)  ) {
		if( ATTR_IF_SOME_WITH_DOWN & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_IF_SOME_WITH_DOWN;
        pText += 17;

    } else if( ! strncmp(pText, "IF_NOT_SOME_WITH_DOWN", 21)  ) {
		if( ATTR_IF_NOT_SOME_WITH_DOWN & pAttrGroupNew->iNum )
        	return retErrInfo("Can not contains C_part and T_part attribute in a group !");

        pAttrGroupNew->iNum |= ATTR_IF_NOT_SOME_WITH_DOWN;
        pText += 21;

    } else if( *pText != ' ' && *pText != '\t' && *pText != '\r' && *pText != '\n' ) {
        pText ++ ;
        return retErrInfo("Unknown attribute !");

    } else {
        for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );  // pass kgf

        if( *pText == '\n' || *pText == '\0' ) {
            iLineNum ++ ;
            pLineHead = pText;

            break;  // while( *pText != '\0' )
        } else
            return retErrInfo("Syntax error !");
    }

    // 跳过属性参数后面的空格
    for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );  // pass kgf
    if( *pText == '\n' )
    {
        pText ++ ;  // pass \n 
        iLineNum ++ ;
        pLineHead = pText;
    }

} // while( *pText != '\0' )

    pAttrGroupNew->next = pstAttrGroupList;
    pstAttrGroupList = pAttrGroupNew;

    return true;
}

bool CZGLanguage::readTranPartOfLineLevel(char *pTmp, struct stLineLevel *pThisLineLevel, char cLineLevelType)
{
    if( strncmp(pTmp,"<<<",3) && strncmp(pTmp,">>>",3) )
    {
        pText = pTmp + 1;
        pLineHead = pTmp - 8; 
        iLineNum -- ;

        return retErrInfo("Miss '<<<' or '>>>' for the tran part !");
    }

    char * pLeft = "__LEFT__";
    unsigned int iLeftLen = 8;

    char * pRight = "__RIGHT__";
    unsigned int iRightLen = 9;

    // Get the self define Left and Right
    if( ! strncmp(pTmp,"<<<",3) )
    {
        pTmp += 3 ;  // pass <<<
        for( ; *pTmp == ' ' || *pTmp == '\t'; pTmp ++ );  // pass kgf

        iLeftLen = 0;
        for( ; (*pTmp > 96 && *pTmp < 123) || (*pTmp > 64 && *pTmp < 91) || *pTmp == '_'; pTmp ++ ) iLeftLen ++;
        if( iLeftLen == 0 )
        {
            pText = pTmp;
            pLineHead = pTmp - 8;
            iLineNum -- ;

            return retErrInfo("Miss left param after '<<<' !");
        }

        pLeft = pTmp - iLeftLen;
// printStrForDebug("Left param", pLeft, iLeftLen);  // debug

        /////////////////////////////////

        for( ; *pTmp == ' ' || *pTmp == '\t'; pTmp ++ );  // pass kgf
        if( *pTmp != ',' )
        {
            pText = pTmp;
            pLineHead = pTmp - 8;
            iLineNum -- ;

            return retErrInfo("Miss ',' here !");
        }

        pTmp ++ ;   // pass ,
        for( ; *pTmp == ' ' || *pTmp == '\t'; pTmp ++ );  // pass kgf

        iRightLen = 0;
        for( ; (*pTmp > 96 && *pTmp < 123) || (*pTmp > 64 && *pTmp < 91) || *pTmp == '_'; pTmp ++ ) iRightLen ++;
        if( iRightLen == 0 )
        {
            pText = pTmp;
            pLineHead = pTmp - 8;
            iLineNum -- ;

            return retErrInfo("Miss right param after ',' !");
        }

        pRight = pTmp - iRightLen;
// printStrForDebug("Right param", pRight, iRightLen);  // debug

        if( iLeftLen == iRightLen && ! strncmp(pLeft, pRight, iLeftLen) )
        {
            pText = pTmp;
            pLineHead = pTmp - 8;
            iLineNum -- ;

            return retErrInfo("Left and Right param can not be the some !");
        }

        for( ; *pTmp == ' ' || *pTmp == '\t'; pTmp ++ );  // pass kgf

    } // if( ! strncmp(pTmp,"<<<",3) )

    if( strncmp(pTmp,">>>",3) )
    {
        pText = pTmp;
        pLineHead = pTmp - 8;
        iLineNum -- ;

        return retErrInfo("Miss '>>>' here !");
    }

    pTmp += 3;  // pass >>>

    ////////////////////////////////

    // Get the tran part list
    pThisLineLevel->pTranPartList = getStringNode();
    memset(pThisLineLevel->pTranPartList, 0x00, sizeof(struct stString));
    struct stString *pTranPartTail = pThisLineLevel->pTranPartList;

    pTranPartTail->pStr = pTmp;

	struct stString * pTranPartTailBf = NULL;

    for( ; *pTmp == ' ' || *pTmp == '\t'; pTmp ++ );  // pass kgf
    if( *pTmp == '\r' || *pTmp == '\n' || ! strncmp(pTmp, "__//__", 6) || ! strncmp(pTmp, "__/*__", 6) )
    {
        pText = pTmp;
        pLineHead = pTmp - 8;
        iLineNum -- ;

        return retErrInfo("Miss content after '>>>' !");
    }
	else if( ! strncmp(pText, "__/*__", 6) )
    {
		pText += 6;  // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;
    }

    for( ; *pTmp != '\r' && *pTmp != '\n' && strncmp(pTmp, "__//__", 6) && strncmp(pTmp, "__/*__", 6); pTmp ++ )
    {
        // 检查是否 左 右 参数
        char cFlag = '\0';
        if( ! strncmp(pTmp, pLeft, iLeftLen) )
            cFlag = 'L';
        else if( ! strncmp(pTmp, pRight, iRightLen) )
            cFlag = 'R';
		else if( cLineLevelType == 'E' && ! strncmp(pTmp, pThisLineLevel->pContentList->pStr, pThisLineLevel->pContentList->iStrLen) )
            cFlag = 'E';

        if( ! cFlag )
			continue ;

        // 保存当期节点
        pTranPartTail->iStrLen = pTmp - pTranPartTail->pStr;  // 注意，这里不是 pTranPartTail->iStrLen ++

        // 若当前 tran 节点 不 为空
        if( pTranPartTail->iStrLen )
        {
            // 新增节点保存左参数
            pTranPartTail->next = getStringNode();
            memset(pTranPartTail->next, 0x00, sizeof(struct stString));
            // pTranPartTail->next->pp = pTranPartTail;   // -> before
            pTranPartTailBf = pTranPartTail; 
            pTranPartTail = pTranPartTail->next;
        } 

        pTranPartTail->cFlag = cFlag;

        if( cFlag == 'L' )
		{
			// __BEF__ 不能有 左 参数
			if( cLineLevelType == 'B' )
    		{
        		pText = pTmp + iLeftLen;
        		pLineHead = pTmp - 8;
        		iLineNum -- ;

        		return retErrInfo("Tran_part of '__BEF__' can not have left param !");
    		}
            else if( cLineLevelType == 'E' )
            {
        		pText = pTmp + iLeftLen;
                pLineHead = pTmp - iLeftLen - 8;
                return retErrInfo("Tran_part of '__ELE__' can not have left param !");
            }

            pTmp += iLeftLen;
		}
        else if( cFlag == 'R' )
		{
            // __AFT__ 不能有 右 参数
            if( cLineLevelType == 'A' )
            {
                pText = pTmp + iRightLen;
                pLineHead = pTmp - 8;
                iLineNum -- ;

                return retErrInfo("Tran_part of '__AFT__' can not have right param !");
            }
            else if( cLineLevelType == 'E' )
            {
                pText = pTmp + iRightLen;
                pLineHead = pTmp - iRightLen - 8;
                return retErrInfo("Tran_part of '__ELE__' can not have right param !");
            }

            pTmp += iRightLen;
		}
		else // if( cFlag == 'E' )
		{
            pTmp += pThisLineLevel->pContentList->iStrLen;
		}

        // 新增预备节点
        pTranPartTail->next = getStringNode();
        memset(pTranPartTail->next, 0x00, sizeof(struct stString));
        // pTranPartTail->next->pp = pTranPartTail;   // -> before
        pTranPartTailBf = pTranPartTail; 
        pTranPartTail = pTranPartTail->next;
        pTranPartTail->pStr = pTmp;

        // do with for : for( ...; ...; pTmp ++)
        pTmp -- ;
        *pTmp = ' ';

    } // for( ; *pTmp != '\r' && *pTmp != '\n' && strncmp(pTmp, "__//__", 6) && strncmp(pTmp, "__/*__", 6); pTmp ++ )

    // 处理最后一个节点
    pTranPartTail->iStrLen = pTmp - pTranPartTail->pStr;  // 注意，这里不是 pTranPartTail->iStrLen ++
    if( pTranPartTail->iStrLen  == 0 )
	{
        // pTranPartTail = (struct stString *)(pTranPartTail->pp);   // go to before node
        freeStringNode( & pTranPartTailBf->next );
        pTranPartTailBf->next = NULL;
	}

	// For __ELE__ end
	if( cLineLevelType == 'E' )
	{
		if( *pTmp == '\r' ) {
			pTmp += 2;
            iLineNum ++ ;
            pLineHead = pTmp;
		} else if( *pTmp == '\n' ) {
			pTmp += 1;
            iLineNum ++ ;
            pLineHead = pTmp;
		}

		pText = pTmp;
	}

    return true;
}

bool CZGLanguage::createNewLine()
{
    struct stLine *pLineNew = getLineNode();
    memset(pLineNew, 0x00, sizeof(struct stLine));

    pLineNew->pName = pLgStr;
    pLineNew->iNameLen = iLgStrLen;

while( *pText != '\0' )
{
    // 注释行
    if( ! strncmp(pText, "__//__", 6) )
    {
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0

        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }
	else if( ! strncmp(pText, "__/*__", 6) )
    {
		pText += 6;   // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }

    if( ! strncmp(pText, "__ELE__ ", 8) || ! strncmp(pText, "__ELE__\t", 8) )
    {
        pText += 8;
        for( ; *pText==' ' || *pText=='\t'; pText ++ );   // pass kgf

        if( *pText == '\r' || *pText == '\n' || *pText == '\0' || ! strncmp(pText,"__//__",6) || ! strncmp(pText,"__/*__",6) )
            return retErrInfo("Miss content after '__ELE__' !");

        struct stLineLevel *pEleNew = getLineLevelNode();
        memset(pEleNew, 0x00, sizeof(struct stLineLevel));

        if( ! getVisibleStr() )
            return false;

        // Check if start with number
        if( *pLgStr >= '0' && *pLgStr <= '9' )
        {
            pText = pLgStr + iLgStrLen;
            pLineHead = pLgStr;

            return retErrInfo("__ELE__ content can not start with number !");
        }

        if( ! strncmp("__BLANK__", pLgStr, iLgStrLen)
         || ! strncmp("__\\b__", pLgStr, iLgStrLen)
         || ! strncmp("__\\t__", pLgStr, iLgStrLen)
         || ! strncmp("__\\n__", pLgStr, iLgStrLen)
         || ! strncmp("__ANY__", pLgStr, iLgStrLen)
         || ! strncmp("__VALUE__", pLgStr, iLgStrLen)
        )
        {
            pText = pLgStr + iLgStrLen;
            pLineHead = pLgStr;

            return retErrInfo("__ELE__ can not be __BLANK__ __\\b__ __\\t__ __\\n__  __VALUE__ __ANY__ !");
        }

        struct stString *pContentNew = getStringNode();
        memset(pContentNew, 0x00, sizeof(struct stString));
        pContentNew->pStr = pLgStr;
        pContentNew->iStrLen = iLgStrLen;

        pEleNew->pContentList = pContentNew;
        pEleNew->iLineNum = iLineNum;

        pEleNew->next = pLineNew->pstEleList;
        pLineNew->pstEleList = pEleNew;

        for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );   // pass kgf
        if( *pText == '\n' )
        {
            pText ++ ;
            iLineNum ++ ;
            pLineHead = pText;
        }
		else if( ! strncmp(pText, "__//__", 6) || ! strncmp(pText, "__/*__", 6) )
		{
			// pass
		}
		else
		{
        	if( ! readTranPartOfLineLevel(pText, pEleNew, 'E') )
            	return false;
		}
// printStrForDebug("__ELE__", pLineNew->pstEleList->pContentList->pStr, pLineNew->pstEleList->pContentList->iStrLen);  // debug
    }
    else if( ! strncmp(pText, "__OPR__ ", 8) || ! strncmp(pText, "__OPR__\t", 8)
          || ! strncmp(pText, "__BEF__ ", 8) || ! strncmp(pText, "__BEF__\t", 8)
          || ! strncmp(pText, "__AFT__ ", 8) || ! strncmp(pText, "__AFT__\t", 8) )
    {
        char cType;

        if( ! strncmp(pText, "__OPR__", 7) )
            cType = 'O';
        else if( ! strncmp(pText, "__BEF__", 7) )
            cType = 'B';
        else if( ! strncmp(pText, "__AFT__", 7) )
            cType = 'A';

        pText += 8;
        for( ; *pText==' ' || *pText=='\t'; pText ++ );   // pass kgf

        if( *pText == '\r' || *pText == '\n' || *pText == '\0' || ! strncmp(pText,"__//__",6) || ! strncmp(pText,"__/*__",6) )
        {
            if( cType == 'B' )
                return retErrInfo("Miss content after '__BEF__' !");
            else if( cType == 'A' )
                return retErrInfo("Miss content after '__AFT__' !");
            else if( cType == 'O' )
                return retErrInfo("Miss content after '__OPR__' !");
        }

        struct stLineLevel *pOprBefAftNew = getLineLevelNode();
        memset(pOprBefAftNew, 0x00, sizeof(struct stLineLevel));

        pOprBefAftNew->iLineNum = iLineNum;

        if( ! getVisibleStr() )
            return false;

        struct stString *pContentNew = getStringNode();
        memset( pContentNew, 0x00, sizeof(struct stString) );
        pContentNew->pStr = pLgStr;
        pContentNew->iStrLen = iLgStrLen;

        pOprBefAftNew->pContentList = pContentNew;

        // Go on to get the content info
        while( true )
        {
            for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );   // pass kgf

            if( *pText == '\n' || *pText == '\0' )
            {
                pText ++ ;
                iLineNum ++ ;
                pLineHead = pText;

                break;
            }

            if( ! strncmp(pText, "__//__", 6) )
            {
                for( ; *pText != '\n' && *pText != '\0'; pText ++ );
                pText ++ ;  // pass \n , \0
                iLineNum ++ ;
                pLineHead = pText;

                break ;
            }
			else if( ! strncmp(pText, "__/*__", 6) )
            {
				pText += 6;   // pass __/*__
        		for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            		if( *pText == '\n' ) {
                		iLineNum ++ ;
                		pLineHead = pText;
            		}
        		}

        		// 最后一整行也注释掉
        		for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        		pText ++ ;  // pass \n , \0
        		iLineNum ++ ;
        		pLineHead = pText;

        		break ;
    		}

            if( ! getVisibleStr() )
                return false;

            pContentNew->next = getStringNode();
            pContentNew = pContentNew->next;
            memset( pContentNew, 0x00, sizeof(struct stString) );
            pContentNew->pStr = pLgStr;
            pContentNew->iStrLen = iLgStrLen;

// printStrForDebug("       ", pContentNew->pStr, pContentNew->iStrLen);  // debug
        } // while( true )

        /////////////////////////////////////////////////////

        struct stLineLevel *pLineLevelTmp = NULL;
        if( cType == 'O' )
            pLineLevelTmp = pLineNew->pstOprList;
        else if( cType == 'B' )
            pLineLevelTmp = pLineNew->pstBefList;
        else // cType == 'A' 
            pLineLevelTmp = pLineNew->pstAftList;

        // Order by Content length of first node
        bool isOrder = false;
        if( pLineLevelTmp == NULL || pOprBefAftNew->pContentList->iStrLen > pLineLevelTmp->pContentList->iStrLen )
        {
            pOprBefAftNew->next = pLineLevelTmp;

            if( cType == 'O' )
                pLineNew->pstOprList = pOprBefAftNew;
            else if( cType == 'B' )
                pLineNew->pstBefList = pOprBefAftNew;
            else // cType == 'A' 
                pLineNew->pstAftList = pOprBefAftNew;

            isOrder = true;
        }
        // Order by Content list node number of first line level
        else if( pOprBefAftNew->pContentList->iStrLen == pLineLevelTmp->pContentList->iStrLen )
        {
            unsigned int iCountNew = 0;
            unsigned int iCountTmp = 0;

            struct stString *pStringTmp = pOprBefAftNew->pContentList;
            for( ; pStringTmp; pStringTmp=pStringTmp->next )
                iCountNew ++ ;

            pStringTmp = pLineLevelTmp->pContentList;
            for( ; pStringTmp; pStringTmp=pStringTmp->next )
                iCountTmp ++ ;

            if( iCountNew >= iCountTmp )
            {
                pOprBefAftNew->next = pLineLevelTmp;

                if( cType == 'O' )
                    pLineNew->pstOprList = pOprBefAftNew;
                else if( cType == 'B' )
                    pLineNew->pstBefList = pOprBefAftNew;
                else // cType == 'A' 
                    pLineNew->pstAftList = pOprBefAftNew;

                isOrder = true;
            }
        }

        if( ! isOrder )
        {
            unsigned int iCountNew = 0;
            struct stString *pStringTmp = pOprBefAftNew->pContentList;
            for( ; pStringTmp; pStringTmp=pStringTmp->next )
                iCountNew ++ ;

            for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
            {
                // Order by Content length of first node
                if( pLineLevelTmp->next == NULL || pOprBefAftNew->pContentList->iStrLen > pLineLevelTmp->next->pContentList->iStrLen )
                {
                    pOprBefAftNew->next = pLineLevelTmp->next;
                    pLineLevelTmp->next = pOprBefAftNew;
                    break;
                }
                // Order by Content list node number
                else if( pOprBefAftNew->pContentList->iStrLen == pLineLevelTmp->next->pContentList->iStrLen )
                {
                    unsigned int iCountTmp = 0;

                    pStringTmp = pLineLevelTmp->next->pContentList;
                    for( ; pStringTmp; pStringTmp=pStringTmp->next )
                        iCountTmp ++ ;

                    if( iCountNew >= iCountTmp )
                    {
                        pOprBefAftNew->next = pLineLevelTmp->next;
                        pLineLevelTmp->next = pOprBefAftNew;
                        break;
                    }
                } // if
            } // for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
        } // if

        ///////////////////////////////////////////////////////
        // Check content
        ///////////////////////////////////////////////////////

        // Get __OPR__ priority
        if( cType == 'O' )
        {
            struct stString *pContentTmp = pOprBefAftNew->pContentList;
            struct stString *pOprEnd = NULL;

            for( ; pContentTmp; pContentTmp=pContentTmp->next )
            {
                // if iPriority
                if( *(pContentTmp->pStr) >= '0' && *(pContentTmp->pStr) <= '9' )
                    break ;

                if( isKeyword(pContentTmp->pStr, pContentTmp->iStrLen) )
                {
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;
                    pLineHead = pContentTmp->pStr;
                    iLineNum -- ;

                    return retErrInfo("__OPR__ can not contain keyword !");
                }

				pOprEnd = pContentTmp;
            }

			// 截断 操作符 和 优先级 的链表关系
			pOprEnd->next = NULL;

            if( pContentTmp == pOprBefAftNew->pContentList )
            {
                pLineHead = pContentTmp->pStr - 8;
                pText = pContentTmp->pStr + 1;
                iLineNum -- ;

                return retErrInfo("Miss content before priority !");
            }

            if( ! pContentTmp ) 
            {
                pLineHead = pOprBefAftNew->pContentList->pStr - 8;
                pText = pOprBefAftNew->pContentList->pStr + pOprBefAftNew->pContentList->iStrLen;
                iLineNum -- ;

                return retErrInfo("Miss priority after '__OPR__' !");
            }

            // if( pContentNew->iStrLen > 7 )
            if( pContentTmp->iStrLen > 7 )
            {
                pLineHead = pContentNew->pStr;
                pText = pContentNew->pStr + pContentNew->iStrLen;
                iLineNum -- ;

                return retErrInfo("Priority of __OPR__ is too long !");
            }

            char mBuf[8];
            memset(mBuf, 0x00, sizeof(mBuf));
            strncpy(mBuf, pContentTmp->pStr, pContentTmp->iStrLen);
            for( int i=0; i<sizeof(mBuf); i++ )
            {
                if( mBuf[i] > 47 && mBuf[i] < 58 )
                    continue;

                if( mBuf[i] == 0 )
                    break;

                // Go back last line
                pText = pContentTmp->pStr + pContentTmp->iStrLen;
                pLineHead = pContentTmp->pStr; 
                iLineNum -- ;

                return retErrInfo("Priority of __OPR__ must be a integer !");
            }

            pOprBefAftNew->iPriority = atoi(mBuf);

// printf("iPriority ; %d\n", pOprBefAftNew->iPriority);  // debug

			////////////////////////////////
            // Get the tran part
			////////////////////////////////
			if( pContentTmp->next )
			{
				char *pTmp = pContentTmp->next->pStr;
				freeStringList(& pContentTmp->next);
				pContentTmp->next = NULL;

            	if( ! readTranPartOfLineLevel(pTmp, pOprBefAftNew, 'O') )
                	return false;
			}
        } 
        else if( cType == 'B' )  // __BEF__
        {
            struct stString *pContentTmp = pOprBefAftNew->pContentList;
            for( ; pContentTmp; pContentTmp=pContentTmp->next )
            {
                // Check if start with number
                if( *(pContentTmp->pStr) >= '0' && *(pContentTmp->pStr) <= '9' )
                {
                    // Go back last line
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;
                    pLineHead = pContentTmp->pStr; 
                    iLineNum -- ;

                    return retErrInfo(cType == 'B' ? "__BEF__ content can not start with number !" : "__AFT__ content can not start with number !");
                }

                if( isKeyword(pContentTmp->pStr, pContentTmp->iStrLen) )
                {
                    if( strncmp("__NAME__", pContentTmp->pStr, pContentTmp->iStrLen) )
                    {
                        pText = pContentTmp->pStr + pContentTmp->iStrLen;
                        pLineHead = pContentTmp->pStr;
                        iLineNum -- ;
                        return retErrInfo("__BEF__ can contain only one keyword : __NAME__ !");
                    }
                    else if( pOprBefAftNew->pContentList == pContentTmp && pContentTmp->next )
                    {
                        pText = pContentTmp->pStr + pContentTmp->iStrLen + pContentTmp->next->iStrLen;
                        pLineHead = pContentTmp->pStr;
                        iLineNum -- ;
                        return retErrInfo("Error : Can not have other content after '__BEF__ __NAME__' !");
                    }
                }

                // if Tran Part
                if( pContentTmp->next && (! strncmp(pContentTmp->next->pStr,"<<<",3) || ! strncmp(pContentTmp->next->pStr,">>>",3)) )
                {
                    char *pTmp = pContentTmp->next->pStr;
                    for( pTmp --; *pTmp == ' ' || *pTmp == '\t'; pTmp -- );
					// 转换配置前要有10个以上空格
                    if( pContentTmp->next->pStr - pTmp > 9 )
                        break ;
                }

            } // for( ; pContentTmp; pContentTmp=pContentTmp->next )

			///////////////////////////////
            // Get the tran part
			///////////////////////////////
            if( pContentTmp )
            {
                char *pTmp = pContentTmp->next->pStr;
                freeStringList(& pContentTmp->next);
                pContentTmp->next = NULL;

                if( ! readTranPartOfLineLevel(pTmp, pOprBefAftNew, 'B') )
                    return false;
            }
        }
        else if( cType == 'A' ) // __AFT__
        {
            struct stString *pContentTmp = pOprBefAftNew->pContentList;
            for( ; pContentTmp; pContentTmp=pContentTmp->next )
            {
                // Check if start with number
                if( *(pContentTmp->pStr) >= '0' && *(pContentTmp->pStr) <= '9' )
                {
                    // Go back last line
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;
                    pLineHead = pContentTmp->pStr; 
                    iLineNum -- ;

                    return retErrInfo(cType == 'B' ? "__BEF__ content can not start with number !" : "__AFT__ content can not start with number !");
                }

                if( isKeyword(pContentTmp->pStr, pContentTmp->iStrLen) )
                {
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;
                    pLineHead = pContentTmp->pStr;
                    iLineNum -- ;

                    return retErrInfo("__AFT__ can not contain keyword !");
                }

				// if Tran Part
				if( pContentTmp->next && (! strncmp(pContentTmp->next->pStr,"<<<",3) || ! strncmp(pContentTmp->next->pStr,">>>",3)) )
				{
					char *pTmp = pContentTmp->next->pStr;
					for( pTmp --; *pTmp == ' ' || *pTmp == '\t'; pTmp -- );
					// 转换配置前要有10个以上空格
					if( pContentTmp->next->pStr - pTmp > 9 )
						break ;
				}
            } // for( ; pContentTmp; pContentTmp=pContentTmp->next )

            ///////////////////////////////
            // Get the tran part
            ///////////////////////////////
            if( pContentTmp )
            {
                char *pTmp = pContentTmp->next->pStr;
                freeStringList(& pContentTmp->next);
                pContentTmp->next = NULL;

                if( ! readTranPartOfLineLevel(pTmp, pOprBefAftNew, 'A') )
                    return false;
            }

        } else
            return retErrInfo("Something error 1 ???");
    }
    else if( ! strncmp(pText, "__SUB__ ", 8) || ! strncmp(pText, "__SUB__\t", 8) )
    {
        pText += 8;

        if( pLineNew->pSubRight )
            return retErrInfo("Error : Line object can have only one __SUB__ !");

        for( ; *pText==' ' || *pText=='\t'; pText ++ );   // pass kgf

        if( *pText == '\r' || *pText == '\n' || *pText == '\0' || ! strncmp(pText,"__//__",6) || ! strncmp(pText,"__/*__",6) )
            return retErrInfo("Miss content after '__SUB__' !");

        // Get Left
        if( ! getVisibleStr() )
            return false;

// printStrForDebug("__SUB__ 1", pLgStr, iLgStrLen);  // debug

        // Check if start with number
        if( *pLgStr >= '0' && *pLgStr <= '9' )
        {
            pText = pLgStr + iLgStrLen;
            pLineHead = pLgStr;

            return retErrInfo("__SUB__ content can not start with number !");
        }

        pLineNew->pSubLeft = pLgStr;
        pLineNew->iSubLeftLen = iLgStrLen;

        ////////////////////////////////////////////
        // Get second content

        for( ; *pText==' ' || *pText=='\t'; pText ++ );   // pass kgf

        if( ! getVisibleStr() )
            return false;

        if( iLgStrLen == 0 || ! strncmp(pLgStr, "__//__", 6) || ! strncmp(pLgStr, "__/*__", 6) )
            return retErrInfo("Miss second content after __SUB__ !");

// printStrForDebug("__SUB__ 2", pLgStr, iLgStrLen);  // debug

        // Check if start with number
        if( *pLgStr >= '0' && *pLgStr <= '9' )
        {
            pText = pLgStr + iLgStrLen;
            pLineHead = pLgStr;
            return retErrInfo("__SUB__ content can not start with number !");
        }

        pLineNew->pSubRight = pLgStr;
        pLineNew->iSubRightLen = iLgStrLen;

        //////////////////////////////////////////////

        for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );   // pass kgf
        if( *pText == '\n' || *pText == '\0' )
        {
            pText ++ ;
            iLineNum ++ ;
            pLineHead = pText;
        }
        else if( strncmp(pText, "__//__", 6) || strncmp(pText, "__/*__", 6) )
            return retErrInfo("Too many content after __SUB__ !");
    }
    else if( ! strncmp(pText, "__SPL__ ", 8) || ! strncmp(pText, "__SPL__\t", 8) )
    {
        pText += 8;

        for( ; *pText==' ' || *pText=='\t'; pText ++ );   // pass kgf

        if( *pText == '\r' || *pText == '\n' || *pText == '\0' || ! strncmp(pText,"__//__",6) || ! strncmp(pText,"__/*__",6) )
            return retErrInfo("Miss content after '__SPL__' !");

        if( ! getVisibleStr() )
            return false;

        pLineNew->pSplit = pLgStr;
        pLineNew->iSplitLen = iLgStrLen;

        ////////////////////////////////////////

        for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );   // pass kgf
        if( *pText == '\n' || *pText == '\0' )
        {
            pText ++ ;
            iLineNum ++ ;
            pLineHead = pText;
        }
		// Get tran part
		else if( ! strncmp(pText,">>>",3) )
		{
			pText += 3;  // pass >>>
			pLineNew->pSplit4Tran = pText;

        	for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );   // pass kgf
			if( *pText == '\n' || ! strncmp(pText,"__//__", 6) || ! strncmp(pText,"__/*__", 6) )
        		return retErrInfo("Miss content after >>> !");

        	for( ; *pText != '\n' && *pText != '\0' && strncmp(pText,"__//__",6) && strncmp(pText,"__/*__",6); pText ++ );

			pLineNew->iSplitLen4Tran = pText - pLineNew->pSplit4Tran;
        	if( *pText == '\n' || *pText == '\0' )
        	{
            	pText ++ ;
            	iLineNum ++ ;
            	pLineHead = pText;
        	}
// printStrForDebug("__SPL__ tran", pLineNew->pSplit4Tran, pLineNew->iSplitLen4Tran);  // debug
		}
    }
    else
    {
        for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );  // pass kgf

        if( *pText == '\n' || *pText == '\0' ) {
            iLineNum ++ ;
            pLineHead = pText;

            break;  // while( *pText != '\0' )
        } else
            return retErrInfo("Syntax error !");
    }

} // while( *pText != '\0' )

    if( pLineNew->pstEleList == NULL )
    {
        pText = pLineNew->pName + pLineNew->iNameLen;
        pLineHead = pLineNew->pName;
        return retErrInfo("This line miss __ELE__ !");
    }

    if( pLineNew->pstOprList == NULL )
    {
        pText = pLineNew->pName + pLineNew->iNameLen;
        pLineHead = pLineNew->pName;
        return retErrInfo("This line miss __OPR__ !");
    }

    pLineNew->next = pstLineList;
    pstLineList = pLineNew;

    return true;
}

bool CZGLanguage::readTranPartOfTree(struct stTree *pThisTree)
{
// printStrForDebug("\nThis is readTranPartOfTree", pThisTree->pName, pThisTree->iNameLen);  // debug

    // if NULL line for first tran line
    char *pTmp = pText;
    for( ; *pTmp== ' ' || *pTmp== '\t' || *pTmp== '\r'; pTmp ++ );
    if( *pTmp == '\n' || *pTmp == '\0' )
        return retErrInfo("Miss content after ----- !");

    struct stTreeTranLevel *pTreeTranLevelTail = NULL;

	char mPathY4FirstNodeOfNewTran[pThisTree->iPathMaxX + 1];
	mPathY4FirstNodeOfNewTran[pThisTree->iPathMaxX] = '\0';

while( *pText != '\0' )
{
    // 注释行
    if( ! strncmp(pText, "__//__", 6) )
    {
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0

        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }
	else if( ! strncmp(pText, "__/*__", 6) )
    {
		pText += 6;   // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }

    // first line of tree tran part
    if( pThisTree->pstTreeTranLevels == NULL )
    {
        bool isNullLine = true;
        for(int i=0; i < pThisTree->iPathMaxX; i ++ )
        {
            if( *(pText+i) == ' ' )
                continue ;

            if( *(pText+i) == '1' || *(pText+i) == 'N' )     // || *(pText+i) == '*' )  for first line !!!
            {
                isNullLine = false;
                continue ;
            }

            pText += i + 1;
            return retErrInfo("Must be '1' or 'N' here !");
        }
        if( isNullLine )
        {
            pText += pThisTree->iPathMaxX;
            return retErrInfo("Miss '1' or 'N' here !");
        }

        //////////////////////////////////

        pThisTree->pstTreeTranLevels = getTreeTranLevelNode();
        memset(pThisTree->pstTreeTranLevels, 0x00, sizeof(struct stTreeTranLevel));
        pTreeTranLevelTail = pThisTree->pstTreeTranLevels;

        pTreeTranLevelTail->pPathY = pText;
        pTreeTranLevelTail->iLineNum = iLineNum;
        pTreeTranLevelTail->isFirstNodeOfNewTran = true;
    }
    // new tran part
    else if( ! strncmp(pText, "-----", 5) )
    {
        // Pass ------
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0

        iLineNum ++ ;
        pLineHead = pText;

        // if NULL line for first tran line
        char *pTmp = pText;
        for( ; *pTmp== ' ' || *pTmp== '\t' || *pTmp== '\r'; pTmp ++ );
        if( *pTmp == '\n' || *pTmp == '\0' )
            return retErrInfo("Miss content after ----- !");

        //////////////////////////////////

        bool isNullLine = true;
        for(int i=0; i < pThisTree->iPathMaxX; i ++ )
        {
            if( *(pText + i) == ' ' )
                continue ;

            // if( *(pText + i) == '1' || *(pText + i) == 'N' || *(pText + i) == '*' )
            if( *(pText + i) == '1' || *(pText + i) == 'N' || *(pText + i) == 'n' || *(pText + i) == '*' )
            {
                isNullLine = false;
                continue ;
            }

            pText += i + 1;
            return retErrInfo("Must be '1' or 'N' or 'n' or '*' here !");
        }
        if( isNullLine )
        {
            pText += pThisTree->iPathMaxX;
            return retErrInfo("Miss '1' or 'N' here !");
        }

        // new tran part
        pTreeTranLevelTail->next = getTreeTranLevelNode();
        pTreeTranLevelTail = pTreeTranLevelTail->next;
        memset(pTreeTranLevelTail, 0x00, sizeof(struct stTreeTranLevel));

        pTreeTranLevelTail->pPathY = pText;
        pTreeTranLevelTail->iLineNum = iLineNum;
        pTreeTranLevelTail->isFirstNodeOfNewTran = true;
    }
    // other line of tree tran part
    else
    {
        // if NULL line
        pTmp = pText;
        for( ; *pTmp== ' ' || *pTmp== '\t' || *pTmp== '\r'; pTmp ++ );
        if( *pTmp == '\n' || *pTmp == '\0' )
        {
            pText = pTmp - 1;
            break;             // while( *pText != '\0' )
        }

        pTreeTranLevelTail->next = getTreeTranLevelNode();
        pTreeTranLevelTail = pTreeTranLevelTail->next;
        memset(pTreeTranLevelTail, 0x00, sizeof(struct stTreeTranLevel));
        pTreeTranLevelTail->pPathY = pText;
        pTreeTranLevelTail->iLineNum = iLineNum;
    }

    pText += pThisTree->iPathMaxX;

    /////////////////////////////////////////////
    // Get other name
    for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf

    char * pCmpKeyWord = NULL;
    unsigned int iCmpKeyWordLen = 0;

    if( *pText == ':' )
    {
        for( pText ++ ; *pText==' ' || *pText=='\t'; pText ++ );  // pass : ...

		if( ! strncmp(pText, "by(", 3) ) {
			pTreeTranLevelTail->cOtherNameType = 'b';
			pText += 3;   // pass by(
        	for( ; *pText==' ' || *pText=='\t'; pText ++ );
		} else if( ! strncmp(pText, "byv(", 4) ) {
			pTreeTranLevelTail->cOtherNameType = 'v';
			pText += 4;   // pass byv(
        	for( ; *pText==' ' || *pText=='\t'; pText ++ );
		} else
			pTreeTranLevelTail->cOtherNameType = '\0';
    
        if( ! getCmpStr() )
            return false;
   
        if( iLgStrLen == 0 )
            return retErrInfo("Miss content after ':' !");
   
        pTreeTranLevelTail->pOtherName = pLgStr;
        pTreeTranLevelTail->iOtherNameLen = iLgStrLen;

		if( pTreeTranLevelTail->cOtherNameType )
		{
        	for( ; *pText==' ' || *pText=='\t'; pText ++ );
			if( *pText != ')' )
            	return retErrInfo("Miss ')' here !");

			pText ++ ;    // ')'
		}

		//////////////////////////////////////////
        // Check other name if exists

		char mPathYBuf[pThisTree->iPathMaxX + 1];
		mPathYBuf[pThisTree->iPathMaxX] = '\0';
		memcpy(mPathYBuf, pThisTree->pstTreeCplLevels->pPathY, pThisTree->iPathMaxX);

// printf("????????????????????????????????????????? isFirstNodeOfNewTran = [%d]\n", pTreeTranLevelTail->isFirstNodeOfNewTran);
// printStrForDebug("pTreeTranLevelTail->pPathY", pTreeTranLevelTail->pPathY, pThisTree->iPathMaxX);

		if( pTreeTranLevelTail->isFirstNodeOfNewTran )
			memcpy(mPathY4FirstNodeOfNewTran, pTreeTranLevelTail->pPathY, pThisTree->iPathMaxX);

        struct stTreeCplLevel *pCmpTreeLevel = pThisTree->pstTreeCplLevels;
        for( ; pCmpTreeLevel; pCmpTreeLevel=pCmpTreeLevel->next )
        {
// printf("pCmpTreeLevel->cSplitFlag=[%c]\n", pCmpTreeLevel->cSplitFlag);

			for(int i=0; i < pThisTree->iPathMaxX; i ++ )
			{
				char cTmp = *(pCmpTreeLevel->pPathY + i);
				if( cTmp == '1' || cTmp == 'N' )
				{
					mPathYBuf[i] = cTmp;
				}

				if( mPathY4FirstNodeOfNewTran[i] != ' ' )
				{
					if( cTmp == '0' )
						mPathY4FirstNodeOfNewTran[i] = cTmp;
					else if( pCmpTreeLevel->cSplitFlag != '+' )
						mPathY4FirstNodeOfNewTran[i] = '*';   // 只是占位
				}
			}
// printf("mPathYBuf : [%s]\n", mPathYBuf);  // debug

            if( pTreeTranLevelTail->pOtherName && pCmpTreeLevel->iOtherNameLen == pTreeTranLevelTail->iOtherNameLen
             && ! strncmp(pCmpTreeLevel->pOtherName, pTreeTranLevelTail->pOtherName, pTreeTranLevelTail->iOtherNameLen) )
            {
/**********************************
printStrForDebug("1111111111111111111111 Cpl  pPath", pCmpTreeLevel->pPathY, pThisTree->iPathMaxX);
          printf("2222222222222222222222 Cpl  pPath : %s\n", mPathYBuf);
printStrForDebug("3333333333333333333333 Tran pPath", pTreeTranLevelTail->pPathY, pThisTree->iPathMaxX);
          printf("4444444444444444444444 T1st pPath : %s\n", mPathY4FirstNodeOfNewTran);
printf("\n");
/**********************************/

                // Check Tran pPathY Vs Cpl pPathY
                for(int i=0; i < pThisTree->iPathMaxX; i ++ )
                {
					// 跳过空转换路径
					if( mPathY4FirstNodeOfNewTran[i] == ' ' )
						continue ;

					// 若Cpl路径节点设置为0，对应的转换区节点也必须为0
					// if( *(pCmpTreeLevel->pPathY + i) == '0' && *(pTreeTranLevelTail->pPathY + i) != '0' )
					if( mPathY4FirstNodeOfNewTran[i] == '0' && *(pTreeTranLevelTail->pPathY + i) != '0' )
					{
                        pText = pTreeTranLevelTail->pPathY + i + 1;
                        return retErrInfo("Must be '0' vs '0' with the some other name in T_part and C_part !");
					}

					// 转换逻辑没有 E
                    if( *(pTreeTranLevelTail->pPathY + i) == ' ' || *(pTreeTranLevelTail->pPathY + i) == 'e' )
                        continue ;

                    if( *(pTreeTranLevelTail->pPathY + i) == '1' 
                     // && ( *(pCmpTreeLevel->pPathY + i) != '1' && *(pCmpTreeLevel->pPathY + i) != 'N' )
                     && ( mPathYBuf[i] != '1' && mPathYBuf[i] != 'N' )
                    )
                    {
                        pText = pTreeTranLevelTail->pPathY + i + 1;
                        return retErrInfo("Must be '1' vs '1'/'N' with the some other name in T_part and C_part !");
                    }
                    else if( *(pTreeTranLevelTail->pPathY + i) != '1' && *(pTreeTranLevelTail->pPathY + i) != 'N'
                          && *(pTreeTranLevelTail->pPathY + i) != ' ' && *(pTreeTranLevelTail->pPathY + i) != 'e'
                          && *(pTreeTranLevelTail->pPathY + i) != '0' 
                          && *(pTreeTranLevelTail->pPathY + i) != '*' && *(pTreeTranLevelTail->pPathY + i) != 'n' )   // add 20240303
                    {
                        pText = pTreeTranLevelTail->pPathY + i + 1;
                        return retErrInfo("Error content here ! 123");
                    }
                }
    
                break ;

            } // if
        } // for( ; pCmpTreeLevel; pCmpTreeLevel=pCmpTreeLevel->next )
    
        if( pCmpTreeLevel == NULL && pTreeTranLevelTail->cOtherNameType != 'b' )
            return retErrInfo("This other name is not defined !");

// printStrForDebug("other name", pTreeTranLevelTail->pOtherName, pTreeTranLevelTail->iOtherNameLen);  // debug
// printStrForDebug("Cmp key word", pCmpTreeLevel->pKeyword, pCmpTreeLevel->iKeywordLen);  // debug

		pCmpKeyWord = pCmpTreeLevel->pKeyword;
		iCmpKeyWordLen = pCmpTreeLevel->iKeywordLen;

    } 
    // else if( pTreeTranLevelTail->isFirstNodeOfNewTran )
    //    return retErrInfo("Miss ':' here !");
	else
    	return retErrInfo("Miss ':' here !");

    /////////////////////////////////////////////
    for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf

    // Get attr
    if( *pText == '@' )
    {
        for( pText ++ ; *pText==' ' || *pText=='\t'; pText ++ );  // pass : kgf

        while( true )
        {
            if( ! getCmpStr() )
                return false;

            if( ! iLgStrLen )
                break ;

// printStrForDebug("Attr", pLgStr, iLgStrLen);  // debug

            // 若是自定义属性组
            if( *pLgStr == '_' ) {
                struct stString *pOneAttrGroup = pstAttrGroupList;
                for(  ; pOneAttrGroup; pOneAttrGroup=pOneAttrGroup->next )
                {
                    if( pOneAttrGroup->iStrLen == iLgStrLen && ! strncmp(pOneAttrGroup->pStr, pLgStr, pOneAttrGroup->iStrLen) )
                    {
                        pTreeTranLevelTail->iAttrFlag |= pOneAttrGroup->iNum;
                        break ;
                    }
                }
                if( ! pOneAttrGroup )
                    return retErrInfo("Unknown attribute group name !");

            } else if( iLgStrLen == 6 && ! strncmp(pLgStr, "STRING", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_STRING;
            else if( iLgStrLen == 4 && ! strncmp(pLgStr, "EXPR", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_EXPR;
            else if( iLgStrLen == 15 && ! strncmp(pLgStr, "IF_SOME_WITH_UP", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_IF_SOME_WITH_UP;
            else if( iLgStrLen == 19 && ! strncmp(pLgStr, "IF_NOT_SOME_WITH_UP", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_IF_NOT_SOME_WITH_UP;
            else if( iLgStrLen == 17 && ! strncmp(pLgStr, "IF_SOME_WITH_DOWN", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_IF_SOME_WITH_DOWN;
            else if( iLgStrLen == 21 && ! strncmp(pLgStr, "IF_NOT_SOME_WITH_DOWN", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_IF_NOT_SOME_WITH_DOWN;
            else if( iLgStrLen == 4 && ! strncmp(pLgStr, "HIDE", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_HIDE;
            else if( iLgStrLen == 11 && ! strncmp(pLgStr, "SKIP_C_EXPR", iLgStrLen) )
                pTreeTranLevelTail->iAttrFlag |= ATTR_SKIP_C_EXPR;
/*******************************************************
            ///////////////////////////////////////////////////////
            // function
            else if( ! strncmp(pLgStr, "setkey", iLgStrLen)  || ! strncmp(pLgStr, "getkey", iLgStrLen)
                  || ! strncmp(pLgStr, "addhead", iLgStrLen) || ! strncmp(pLgStr, "gethead", iLgStrLen)
                  || ! strncmp(pLgStr, "addtail", iLgStrLen) || ! strncmp(pLgStr, "gettail", iLgStrLen)
                  || ! strncmp(pLgStr, "delkey", iLgStrLen)  || ! strncmp(pLgStr, "dellist", iLgStrLen)
            )
            {
                struct stExprInfo * pAttrExprNew = createOneExprInfo();
                if( ! pAttrExprNew )
                    return false;

                // 如果是第一个函数
                if( ! pTreeTranLevelTail->pAttrExpr )
                    pTreeTranLevelTail->pAttrExpr = pAttrExprNew;
                // 如果是第N个函数, 拼接到最后
                else {
                    struct stExprInfo * pAttrExprTail = pTreeTranLevelTail->pAttrExpr;
                    for( ; pAttrExprTail->next; pAttrExprTail=pAttrExprTail->next );

                    pAttrExprTail->next = pAttrExprNew;
                    pAttrExprNew->before = pAttrExprTail;
                }

********************************************************
struct stExprInfo * pExprInfoTmp = pTreeTranLevelTail->pAttrExpr;
for( ; pExprInfoTmp; pExprInfoTmp=pExprInfoTmp->next )
{
    if( ! pExprInfoTmp->cType ) {
        printStrForDebug("Expr info ", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);
        printf("     line  : %d\n", pExprInfoTmp->iLevel);
    } else {
        printStrForDebug("     Value", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);
        printf("     Level : %d\n", pExprInfoTmp->iLevel);
        printf("     Type  : %c\n", pExprInfoTmp->cType);
        printf("---------------------------------\n");
    }
}
********************************************************
            } 
*******************************************************/
            else
                return retErrInfo("Error attribute for T_part !");

            for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf

        } // while( true )

        if( *pText != '|' && *pText != '/' && *pText != '\\' && *pText != '+' )
            return retErrInfo("Error attribute after '@' !");
    }

    // Get key word
    if( *pText != '|' && *pText != '/' && *pText != '\\' )
        return retErrInfo("Miss '|', '/' or '\\'  here!");

    pTreeTranLevelTail->cSplitFlag = *pText;

    pText ++ ;          // pass | \ / ....

	// 获得缩进信息
	pTreeTranLevelTail->pIndentHead = pText;
    for( ; *pText==' ' || *pText=='\t'; pText ++ )
		pTreeTranLevelTail->iIndentLen ++ ;

	if( ATTR_EXPR & pTreeTranLevelTail->iAttrFlag ) {
        if( ! getCmpStr() )
            return false;
	} else if( ! getVisibleStr() )
        return false;

	if( iLgStrLen == 0 )
	{
        return retErrInfo("Error content here !");
	}

	if( ATTR_STRING & pTreeTranLevelTail->iAttrFlag )
	{
		for( ; *pText != '\r' && *pText != '\n' && *pText != '\0'; pText ++ )
			iLgStrLen ++ ;
	}
	else if( ATTR_EXPR & pTreeTranLevelTail->iAttrFlag 
          && (  ! strncmp(pLgStr, "getkey", iLgStrLen) || ! strncmp(pLgStr, "gethead", iLgStrLen) || ! strncmp(pLgStr, "gettail", iLgStrLen)
             || ! strncmp(pLgStr, "ifnull", iLgStrLen) || ! strncmp(pLgStr, "if", iLgStrLen)
             )
    )
	{
// printf("ATTR_EXPR !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");

        struct stExprInfo * pValueExprNew = createOneExprInfo();
        if( ! pValueExprNew )
            return false;

        // 如果是第一个函数
        if( ! pTreeTranLevelTail->pValueExpr )
            pTreeTranLevelTail->pValueExpr = pValueExprNew;
        // 如果是第N个函数, 拼接到最后
        else {
            struct stExprInfo * pValueExprTail = pTreeTranLevelTail->pValueExpr;
            for( ; pValueExprTail->next; pValueExprTail=pValueExprTail->next );

            pValueExprTail->next = pValueExprNew;
            pValueExprNew->before = pValueExprTail;
        }
	}

// printStrForDebug("Cmp  key word", pCmpKeyWord, iCmpKeyWordLen);  // debug
// printStrForDebug("Tran key word", pLgStr, iLgStrLen);  // debug

	if( pTreeTranLevelTail->pValueExpr ) {
		// 若为表达式，需要识别表达式中的变量
		struct stExprInfo * pExprInfoTmp = pTreeTranLevelTail->pValueExpr;
		for( ; pExprInfoTmp; pExprInfoTmp=pExprInfoTmp->next )
		{
// if( pExprInfoTmp->iStrLen != TYPE_POINTER )
// printStrForDebug("?????? pExprInfoTmp", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);  // debug

			// 若和 CPL 部分的名称一样
			if( iCmpKeyWordLen = pExprInfoTmp->iStrLen && ! strncmp(pExprInfoTmp->pStr, pCmpKeyWord, pExprInfoTmp->iStrLen) )
			{
// printStrForDebug("Got it", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);  // debug
				pExprInfoTmp->pStr = "?";
				pExprInfoTmp->iStrLen = 1;
			}
		}
	} else if( iCmpKeyWordLen == iLgStrLen && ! strncmp(pCmpKeyWord, pLgStr, iLgStrLen) ) {
    	pTreeTranLevelTail->pKeyword = NULL;
    	pTreeTranLevelTail->iKeywordLen = 0;
	} else if( iLgStrLen == 6 && ! strncmp(pLgStr, "__\\n__", iLgStrLen) ) {
    	pTreeTranLevelTail->pKeyword = "\n";
    	pTreeTranLevelTail->iKeywordLen = 1;
	} else if( iLgStrLen == 6 && ! strncmp(pLgStr, "__\\t__", iLgStrLen) ) {
    	pTreeTranLevelTail->pKeyword = "\t";
    	pTreeTranLevelTail->iKeywordLen = 1;
	} else if( iLgStrLen == 6 && ! strncmp(pLgStr, "__\\b__", iLgStrLen) ) {
    	pTreeTranLevelTail->pKeyword = " ";
    	pTreeTranLevelTail->iKeywordLen = 1;
	} else {
    	pTreeTranLevelTail->pKeyword = pLgStr;
    	pTreeTranLevelTail->iKeywordLen = iLgStrLen;
	}

    /////////////////////////////////////////////
    // Go to next line
    for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );
    if( *pText == '\n' ) {
        pText ++ ;
        pLineHead = pText;
        iLineNum ++ ;
    } else if( strncmp(pText, "__//__", 6) || strncmp(pText, "__/*__", 6) ) {
        pText ++ ;
        return retErrInfo("Error content here !");
    }

} // while( *pText != '\0' )

/***************************************************
// * debug
pTreeTranLevelTail = pThisTree->pstTreeTranLevels;
for( ; pTreeTranLevelTail; pTreeTranLevelTail=pTreeTranLevelTail->next )
{
    if( pTreeTranLevelTail->isFirstNodeOfNewTran )
        printf("-------------------------\n");

    printf("\n");
    if( pTreeTranLevelTail->pOtherName )
        printStrForDebug("other name", pTreeTranLevelTail->pOtherName, pTreeTranLevelTail->iOtherNameLen);  // debug
    else
        printf("other name : %d\n", pTreeTranLevelTail->iOtherNameLen);  // debug

    printf("Attr : %x\n", pTreeTranLevelTail->iAttrFlag);  // debug

    printStrForDebug("key word", pTreeTranLevelTail->pKeyword, pTreeTranLevelTail->iKeywordLen);  // debug
}
/***************************************************/

    return true;
}

struct stExprInfo *CZGLanguage::createOneExprInfo()
{
// printf("createOneExprInfo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");

	// 首节点，保存表达式行号等信息
	struct stExprInfo * pNewExprInfo = (struct stExprInfo *)getStringNode();
	memset(pNewExprInfo, 0x00, sizeof(struct stExprInfo));

	pNewExprInfo->pStr = pLgStr;
	pNewExprInfo->iLevel = iLineNum;

    // 函数名节点
	pNewExprInfo->next = (struct stExprInfo *)getStringNode();
	memset(pNewExprInfo->next, 0x00, sizeof(struct stExprInfo));
	pNewExprInfo->next->before = pNewExprInfo;
	pNewExprInfo = pNewExprInfo->next;

	if( *pText != '(' )
	{
        retErrInfo("Miss '(' here !");
		return NULL;
	}

	pText ++ ;    // pass (

	pNewExprInfo->pStr = pLgStr;
	pNewExprInfo->iStrLen = iLgStrLen;
	pNewExprInfo->iLevel = 1;
	pNewExprInfo->cType = 'F';

	unsigned int iCurrLevel = pNewExprInfo->iLevel;

while(true)
{
	if( *pText == ')' )
	{
// printf("111111111111111111111 iCurrLevel = %d\n", iCurrLevel);

		pText ++ ;          // pass )

		if( iCurrLevel > 1 )
		{
			iCurrLevel -- ;
			continue ;
		}

		// 表达式总长度
		pNewExprInfo->before->iStrLen = pText - pNewExprInfo->before->pStr;
		break;
	}

	if( *pText == ',' )
		pText ++ ;   // pass ,

	for( ; *pText == ' '; pText ++ );

    if( ! getCmpStr() )
        return NULL;

/*************************
    if( iLgStrLen == 0 )
	{
		pText ++ ;
        retErrInfo("Syntax error !");
		return NULL;
	}
*************************/

    struct stExprInfo * pNewNode = (struct stExprInfo *)getStringNode();
    memset(pNewNode, 0x00, sizeof(struct stExprInfo));

	// 函数名称
    if( iLgStrLen 
     && (  ! strncmp(pLgStr, "setkey", iLgStrLen)  || ! strncmp(pLgStr, "getkey", iLgStrLen)
        || ! strncmp(pLgStr, "addhead", iLgStrLen) || ! strncmp(pLgStr, "gethead", iLgStrLen)
        || ! strncmp(pLgStr, "addtail", iLgStrLen) || ! strncmp(pLgStr, "gettail", iLgStrLen)
        || ! strncmp(pLgStr, "delkey", iLgStrLen)  || ! strncmp(pLgStr, "dellist", iLgStrLen)

        || ! strncmp(pLgStr, "ifnull", iLgStrLen)  || ! strncmp(pLgStr, "if", iLgStrLen)
        || ! strncmp(pLgStr, "and", iLgStrLen)  || ! strncmp(pLgStr, "or", iLgStrLen) || ! strncmp(pLgStr, "not", iLgStrLen)
        || ! strncmp(pLgStr, "eq", iLgStrLen)  || ! strncmp(pLgStr, "neq", iLgStrLen)
        )
    ) {
		if( *pText != '(' )
		{
        	retErrInfo("Miss '(' here !");
			return NULL;
		}

		pText ++ ;   // pass (

		/////////////////////////////

		pNewNode->pStr = pLgStr;
		pNewNode->iStrLen = iLgStrLen;
		iCurrLevel ++ ;
		pNewNode->iLevel = iCurrLevel;
		pNewNode->cType = 'F';    // 函数名

		// 将新节点插到 pNewExprInfo 和 pNewExprInfo->before 之间
		pNewNode->before = pNewExprInfo->before;
		pNewNode->next = pNewExprInfo;

		pNewExprInfo->before = pNewNode;
		pNewNode->before->next = pNewNode;

	// 函数参数
	} else {
    	if( iLgStrLen == 0 )
		{
			if( *pText == '"' || *pText == '\'' || *pText == '`' || *pText == '^' )
			{
				char cTmp = *pText;

				pText ++ ;   // pass ' " `
				pLgStr = pText;

				for( ; *pText != cTmp && *pText != '\n' && *pText != '\0'; pText ++ )
                    iLgStrLen ++ ;

				pText ++ ;   // pass ' " `

            } else {
				pText ++ ;
        		retErrInfo("Syntax error !");
				return NULL;
			}
		}

        pNewNode->pStr = pLgStr;
        pNewNode->iStrLen = iLgStrLen;
        pNewNode->iLevel = iCurrLevel;
        pNewNode->cType = 'P';   // 参数

        // 将新节点插到 pNewExprInfo 和 pNewExprInfo->before 之间
        pNewNode->before = pNewExprInfo->before;
        pNewNode->next = pNewExprInfo;

        pNewExprInfo->before = pNewNode;
        pNewNode->before->next = pNewNode;
	}

	pNewExprInfo = pNewNode;

} // while(true)

/********************************************************/
if( IF_PRINT )
{
struct stExprInfo * pExprInfoTmp = pNewExprInfo->before;
printStrForDebug("Expr info ", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);
printf("     line  : %d\n", pExprInfoTmp->iLevel);

for( pExprInfoTmp=pExprInfoTmp->next; pExprInfoTmp; pExprInfoTmp=pExprInfoTmp->next )
{
	printStrForDebug("     Value", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);
	printf("     Level : %d\n", pExprInfoTmp->iLevel);
	printf("     Type  : %c\n", pExprInfoTmp->cType);
	printf("---------------------------------\n");
}
}
/********************************************************/

	return pNewExprInfo->before;
}

bool CZGLanguage::createNewTree(char cDefType, unsigned int iPriority)
{
    struct stTree *pTreeNew = getTreeNode();
    memset(pTreeNew, 0x00, sizeof(struct stTree));

    pTreeNew->cType = cDefType;
    pTreeNew->pName = pLgStr;
    pTreeNew->iNameLen = iLgStrLen;
    pTreeNew->iPathMaxX = 0;
    pTreeNew->iPriority = iPriority;

    struct stTreeCplLevel *pTreeLevelTail = NULL;
    unsigned int iCount = 0;

    char *pPathY4Check = NULL;

while( *pText != '\0' )
{
    // 注释行
    if( ! strncmp(pText, "__//__", 6) )
    {
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0

        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }
    else if( ! strncmp(pText, "__/*__", 6) )
    {
		pText += 6;   // pass __/*__
        for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            if( *pText == '\n' ) {
                iLineNum ++ ;
                pLineHead = pText;
            }
        }

		pText += 6;  // pass __*/__

        // 最后一整行也注释掉
        for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        pText ++ ;  // pass \n , \0
        iLineNum ++ ;
        pLineHead = pText;

        continue ;
    }

    iCount ++ ;

    bool is0_NULL = false;
    bool isE_e = false;
    struct stTreeCplLevel * pTreeLevelBf = NULL;

    // First line after __DEF_PATH__ / __DEF_SUB_PATH__
    if( pTreeNew->pstTreeCplLevels == NULL ) {

        if( *pText != '0' && *pText != '1' && *pText != 'N' )
        {
            if( cDefType == 'P' )
                return retErrInfo("Miss content after __DEF_PATH__ !");
            else if( cDefType == 'p' )
                return retErrInfo("Miss content after __DEF_SUB_PATH__ !");
            else
                return retErrInfo("Something error 2 ???");
        }

        pTreeNew->pstTreeCplLevels = getTreeCplLevelNode();
        memset(pTreeNew->pstTreeCplLevels, 0x00, sizeof(struct stTreeCplLevel));
        pTreeNew->pstTreeCplLevels->pPathY = pText;
        pTreeNew->pstTreeCplLevels->iLineNum = iLineNum;
        // 别名可有可无，先当作没有，按顺序给值iOtherNameLen
        pTreeNew->pstTreeCplLevels->iOtherNameLen = iCount;

        for( ; *pText=='0'||*pText=='1'||*pText=='N'; pText ++ )
        {
            pTreeNew->iPathMaxX ++ ;
        }

        if( pTreeNew->iPathMaxX == 0 || ( *pText != ' ' && *pText != '\t' ) )
        {
            return retErrInfo("Error content in this line !");
        }

// printf("pTreeNew->iPathMaxX : %d\n", pTreeNew->iPathMaxX);  // debug

        pTreeLevelTail = pTreeNew->pstTreeCplLevels;

        // for check 
        pPathY4Check = (char *)malloc(pTreeNew->iPathMaxX + 4);
        memset(pPathY4Check, 0x00, pTreeNew->iPathMaxX + 4);
        strncpy(pPathY4Check, pTreeLevelTail->pPathY, pTreeNew->iPathMaxX);

    // Other line after __DEF_PATH__/__DEF_SUB_PATH__
    } else {

        // if ----- line
        if( ! strncmp("-----", pText, 5) )
        {
            pText += 5;  // pass -----

            for( ; *pText != '\n' && *pText != '\0'; pText ++ );
            if( *pText == '\n' )
            {
                pLineHead = pText + 1;
                iLineNum ++ ;

                pText ++ ;
            }

            if( readTranPartOfTree(pTreeNew) )
                break ;    // while( *pText != '\0' )

            return false;
        }

        // if NULL line
        char *pTmp = pText;
        for( ; *pTmp== ' ' || *pTmp== '\t' || *pTmp== '\r'; pTmp ++ );
        if( *pTmp == '\n' || *pTmp == '\0' )
		{
			pText = pTmp - 1;
            break ;
		}

        pTreeLevelBf = pTreeLevelTail;

        pTreeLevelTail->next = getTreeCplLevelNode();
        pTreeLevelTail = pTreeLevelTail->next;
        memset(pTreeLevelTail, 0x00, sizeof(struct stTreeCplLevel));
        pTreeLevelTail->pPathY = pText;
        pTreeLevelTail->iOtherNameLen = iCount;   // 别名可有可无，先当作没有，按顺序给值iOtherNameLen
        pTreeLevelTail->iLineNum = iLineNum;

        is0_NULL = false;
        isE_e = false;

        for( int i=0; i < pTreeNew->iPathMaxX ; i ++ )
        {
            if( *pText == 'N' || *pText == '1' )
            {
                *(pPathY4Check + i) = *pText;

                pText ++ ;
                continue;
            }
            else if( *pText == 'e' || *pText == 'E' )
            {
                if( *(pPathY4Check + i) != 'N' && *(pPathY4Check + i) != 'n' )
                {
                    pText ++ ;
                    return retErrInfo("Miss 'N' before 'e' or 'E' !");
                    // return retErrInfo("Miss 'N' before 'e' !");
                }

                *(pPathY4Check + i) = *pText;
                pText ++ ;
                continue;
            }
            else if( *pText == ' ' )
            {
                if( *(pPathY4Check + i) == '0' )
                    is0_NULL = true;

                if( *(pPathY4Check + i) == 'e' || *(pPathY4Check + i) == 'E' )
                    isE_e = true;

                pText ++ ;
                continue;
            }
            else if( *pText == '+' )
            {
                if( *(pPathY4Check+i) == '0' || *(pPathY4Check+i) == 'e' ||  *(pPathY4Check+i) == 'E' )
                {
                    pText ++ ;
                    return retErrInfo("Can not be 'e', 'E' or '0' before '+' !");
                    // return retErrInfo("Can not be 'e' or '0' before '+' !");
                }

                pText ++ ;
                continue;
            }
            else if( *pText == '0' )
            {
                pText ++ ;
                continue;
            }

            pText ++ ;
            return retErrInfo("Error content in this line !");
        }
    }

    for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf

    // Get other name
    if( *pText == ':' )
    {
        for( pText ++ ; *pText==' ' || *pText=='\t'; pText ++ );  // pass : kgf

        if( ! getCmpStr() )
            return false;

        if( iLgStrLen > 0 )
        {
            if( *pLgStr >= '0' && *pLgStr <= '9' )
                return retErrInfo("The other name can not start with number.");

            pTreeLevelTail->pOtherName = pLgStr;
            pTreeLevelTail->iOtherNameLen = iLgStrLen;

            // Check other name if duplicate
// printStrForDebug("other name", pTreeLevelTail->pOtherName, pTreeLevelTail->iOtherNameLen);
            struct stTreeCplLevel * pTreeLevelTmp = pTreeNew->pstTreeCplLevels;
            for( ; pTreeLevelTmp != pTreeLevelTail; pTreeLevelTmp=pTreeLevelTmp->next )
            {
                if( pTreeLevelTmp->pOtherName  // 20230527
                 && pTreeLevelTmp->iOtherNameLen == pTreeLevelTail->iOtherNameLen
                 && ! strncmp(pTreeLevelTmp->pOtherName, pTreeLevelTail->pOtherName, pTreeLevelTail->iOtherNameLen) )
                {
                    return retErrInfo("The other name can not be duplicate");
                }
            }

            for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf
        }
        else if( *pText != '^' && *pText != '@' && *pText != '|' && *pText != '/' && *pText != '\\' && *pText != '+' )
        {
            pText ++ ;
            return retErrInfo("Error other name after ':' !");
        }
    }

    // Get priority
    if( *pText == '^' )
    {
        for( pText ++ ; *pText==' ' || *pText=='\t'; pText ++ );  // pass : kgf

        if( ! getInt() )
            return false;

        if( iLgStrLen > 7 ) {
            
            return retErrInfo("The Priority is too long !");

        } else if( iLgStrLen > 0 ) {
            char mBuf[12];
            memset(mBuf, 0x00, sizeof(mBuf));
            strncpy(mBuf, pLgStr, iLgStrLen);

            pTreeLevelTail->iPriority = atoi(mBuf);

            for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf

        } else if( *pText != '@' && *pText != '|' && *pText != '/' && *pText != '\\' && *pText != '+' ) {

            pText ++ ;
            return retErrInfo("Error priority after '^' !");
        }
    }

/***************************************************
if( pTreeLevelTail->iPriority > 0 )
    printf("Level priority : %d\n", pTreeLevelTail->iPriority);
***************************************************/

    // Get attribute
    if( *pText == '@' )
    {
        for( pText ++ ; *pText==' ' || *pText=='\t'; pText ++ );  // pass : kgf

        while( true )
        {
            if( ! getCmpStr() )
                return false;

            // if( ! iLgStrLen )
			if( ! iLgStrLen && *pLgStr != '%' )
                break ;

// printStrForDebug("Attr", pLgStr, iLgStrLen);  // debug

            // 若是自定义属性组
            if( *pLgStr == '_' )
            {
                struct stString *pOneAttrGroup = pstAttrGroupList;
                for(  ; pOneAttrGroup; pOneAttrGroup=pOneAttrGroup->next )
                {
                    if( pOneAttrGroup->iStrLen == iLgStrLen && ! strncmp(pOneAttrGroup->pStr, pLgStr, pOneAttrGroup->iStrLen) )
                    {
                        pTreeLevelTail->iAttrFlag |= pOneAttrGroup->iNum;
                        break ;
                    }
                }
                if( ! pOneAttrGroup )
                    return retErrInfo("Unknown attribute group name !");
            }
			// 20260113 针对常量TYPE_CONT的匹配完整性优化
            else if( *pLgStr == '%' )
            {
				// %属性 只能定义一次
				if( ATTR_CONT_MATCH_RULE & pTreeLevelTail->iAttrFlag )
					return retErrInfo("The number of '%' attribute can not more than one !");

				pText ++ ;  // pass %
				
				if( ! getCmpStr() )
					return false;
				
				if( ! iLgStrLen )
					return retErrInfo("Miss STR object name after '%' !");

				pTreeLevelTail->pStr4MatchRule = findStrName(pLgStr, iLgStrLen);
				if( ! pTreeLevelTail->pStr4MatchRule )
                    return retErrInfo("Unknown STR object name !");

				pTreeLevelTail->iAttrFlag |= ATTR_CONT_MATCH_RULE;
            }
            else if( iLgStrLen == 6 && ! strncmp(pLgStr, "STRING", iLgStrLen) )
                pTreeLevelTail->iAttrFlag |= ATTR_STRING;
            else if( iLgStrLen == 11 && ! strncmp(pLgStr, "SKIP_INDENT", iLgStrLen) )
                pTreeLevelTail->iAttrFlag |= ATTR_SKIP_INDENT;
            else if( iLgStrLen == 8 && ! strncmp(pLgStr, "CAN_SKIP", iLgStrLen) )
                pTreeLevelTail->iAttrFlag |= ATTR_CAN_SKIP;
            else if( iLgStrLen == 9 && ! strncmp(pLgStr, "NEXT_LINE", iLgStrLen) )
                pTreeLevelTail->iAttrFlag |= ATTR_NEXT_LINE;
            else if( iLgStrLen == 10 && ! strncmp(pLgStr, "NEXT_LINES", iLgStrLen) )
                pTreeLevelTail->iAttrFlag |= ATTR_NEXT_LINES;
            else if( iLgStrLen == 12 && ! strncmp(pLgStr, "NOT_EXPR_END", iLgStrLen) )
                pTreeLevelTail->iAttrFlag |= ATTR_NOT_EXPR_END;
			///////////////////////////////////////////////////////
			// function
            else if( ! strncmp(pLgStr, "setkey", iLgStrLen)  // || ! strncmp(pLgStr, "getkey", iLgStrLen) 
                  || ! strncmp(pLgStr, "addhead", iLgStrLen) // || ! strncmp(pLgStr, "gethead", iLgStrLen) 
                  || ! strncmp(pLgStr, "addtail", iLgStrLen) // || ! strncmp(pLgStr, "gettail", iLgStrLen) 
                  || ! strncmp(pLgStr, "delkey", iLgStrLen) || ! strncmp(pLgStr, "dellist", iLgStrLen)
                  || ! strncmp(pLgStr, "if", iLgStrLen)
            )
			{
				struct stExprInfo * pAttrExprNew = createOneExprInfo();
				if( ! pAttrExprNew )
					return false;

				// 如果是第一个函数
				if( ! pTreeLevelTail->pAttrExpr )
					pTreeLevelTail->pAttrExpr = pAttrExprNew;
				// 如果是第N个函数, 拼接到最后
				else {
					struct stExprInfo * pAttrExprTail = pTreeLevelTail->pAttrExpr;
					for( ; pAttrExprTail->next; pAttrExprTail=pAttrExprTail->next );

					pAttrExprTail->next = pAttrExprNew;
					pAttrExprNew->before = pAttrExprTail;
				}

/********************************************************
struct stExprInfo * pExprInfoTmp = pTreeLevelTail->pAttrExpr;
for( ; pExprInfoTmp; pExprInfoTmp=pExprInfoTmp->next )
{
	if( ! pExprInfoTmp->cType ) {
		printStrForDebug("Expr info ", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);
		printf("     line  : %d\n", pExprInfoTmp->iLevel);
	} else {
    	printStrForDebug("     Value", pExprInfoTmp->pStr, pExprInfoTmp->iStrLen);
    	printf("     Level : %d\n", pExprInfoTmp->iLevel);
    	printf("     Type  : %c\n", pExprInfoTmp->cType);
    	printf("---------------------------------\n");
	}
}
/********************************************************/
			} else
                return retErrInfo("Error attribute for C_part !");

            for( ; *pText==' ' || *pText=='\t'; pText ++ );  // pass kgf

        } // while( true )

        if( *pText != '|' && *pText != '/' && *pText != '\\' && *pText != '+' )
            return retErrInfo("Error attribute after '@' !");
    }

    ////////////////////////////////////////////////////

    if( *pText != '|' && *pText != '/' && *pText != '\\' && *pText != '+' )
    {
        pText ++ ;
        return retErrInfo("Miss '|', '/', '\\' or '+' !");
    }

    if( *pText == '|' || *pText == '/' || *pText == '\\' )
    {
        if( is0_NULL )
        {
            pText ++ ;
            return retErrInfo("Miss first '1','N' before '|', '/' or '\\' !");
        }

        if( isE_e )
        {
            pText ++ ;
            return retErrInfo("Miss '1','N' after 'e' or 'E' !");
            // return retErrInfo("Miss '1','N' after 'e' !");
        }
    } 

    pTreeLevelTail->cSplitFlag = *pText;

	if( pTreeLevelTail->cSplitFlag == '+' && (ATTR_CAN_SKIP & pTreeLevelTail->iAttrFlag) )
	{
		pText ++ ;
        return retErrInfo("Can not has attribute: CAN_SKIP before '+' !");
	}

    if( cIndentType == INDENT_COMPILER || cIndentType == INDENT_COMPILER_TRANSLATOR ) {

        pText ++ ;    // pass '|', '/', '\' or '+'

        for( ; *pText == ' '; pText ++ )
            pTreeLevelTail->iIndent ++ ;

        if( *pText == '\t' )
            return retErrInfo("Tabs can not used here when '__DEF_INDENT__ INDENT_COMPILER or INDENT_COMPILER_TRANSLATOR'");

        if( pTreeLevelTail->cSplitFlag == '+' && pTreeLevelBf->iIndent != pTreeLevelTail->iIndent )
            return retErrInfo("The indent of '+' must be the some with '| / \\'");

    } else 
        for( pText ++ ; *pText==' '||*pText=='\t'; pText ++ );   // pass '|', '/' or '+', kgf

    if( ! getVisibleStr() )
        return false;

    if( iLgStrLen == 0 )
        return retErrInfo("Miss content after '|', '/', '\\' or '+' !");

	// 20230917
    // if( iLgStrLen > MAX_NAME_SZ )
        // return retErrInfo("Too long content after '|', '/', '\\' or '+' !");

    if( ATTR_STRING & pTreeLevelTail->iAttrFlag )
    {
        for( ; *pText != '\r' && *pText != '\n' && *pText != '\0'; pText ++ )
            iLgStrLen ++ ;
    }

    pTreeLevelTail->pKeyword = pLgStr;
    pTreeLevelTail->iKeywordLen = iLgStrLen;

// printStrForDebug("Keyword", pTreeLevelTail->pKeyword, pTreeLevelTail->iKeywordLen); // debug
// printf("------------------------------------------------\n");

    for( ; *pText==' '||*pText=='\t'||*pText=='\r'; pText ++ );   // pass kgf
    if( *pText == '\n' )
    {
        pText ++ ;   // pass \n
        iLineNum ++ ;
        pLineHead = pText;
    }

    ///////////////////////////////////////////////////////
    // check
    ///////////////////////////////////////////////////////

    // Check pPathY when cSplitFlag='+'
    if( pTreeLevelTail->cSplitFlag == '+' )
    {
        for(int i=0; i < pTreeNew->iPathMaxX; i ++ )
        {
            if( * (pTreeLevelTail->pPathY + i) != ' ' )
            {
                if( *(pText-1) == '\n' )
                    iLineNum -- ;

                pLineHead = pTreeLevelTail->pPathY;
                pText = pTreeLevelTail->pPathY + i + 1;

                return retErrInfo("Error : Path info must be ' ' before '+' !");
            }
        }
    }

} // while( *pText != '\0' )
	

/***************************************
// DEBUG
printStrForDebug("createNewTree", pTreeNew->pName, pTreeNew->iNameLen);
struct stTreeCplLevel * pTmp = pTreeNew->pstTreeCplLevels;
for( ; pTmp; pTmp=pTmp->next )
{
    printf("%c : %c %d %d %d", pTmp->pPathY[0]
	                         , pTmp->cSplitFlag
	                         , pTmp->cType
							 , pTmp->iIndent
							 , pTmp->iAttrFlag
							 );
printStrForDebug("", pTmp->pKeyword, pTmp->iKeywordLen);
}

/****************************************/

    free(pPathY4Check);

    pTreeNew->next = pstTreeList;
    pstTreeList = pTreeNew;

    return true;
}

bool CZGLanguage::isKeyword(char *pStr, unsigned int iStrLen)
{
    if( ! strncmp("__\\b__", pStr, iStrLen)        // 空格 
     || ! strncmp("__\\t__", pStr, iStrLen)        // 制表符
     || ! strncmp("__\\n__", pStr, iStrLen)        // 换行符、文件结束符
     || ! strncmp("__BLANK__", pStr, iStrLen)      // 空字符串
     || ! strncmp("__ANY__", pStr, iStrLen)        // 某个明确节点前的所有内容
     || ! strncmp("__VALUE__", pStr, iStrLen)      // 值
    )
        return true;

    return false;
}

struct stStr * CZGLanguage::findStrName(char *pStr, unsigned int iStrLen)
{
    struct stStr *pStrTmp = pstStrList;

    for( ; pStrTmp; pStrTmp=pStrTmp->next )
    {
        if( iStrLen == pStrTmp->iNameLen && ! strncmp(pStr, pStrTmp->pName, iStrLen) )
            return pStrTmp;
    }

    return NULL;
}

struct stLine * CZGLanguage::findLineName(char *pStr, unsigned int iStrLen)
{
    struct stLine *pLineTmp = pstLineList;

    for( ; pLineTmp; pLineTmp=pLineTmp->next )
    {
        if( iStrLen == pLineTmp->iNameLen && ! strncmp(pStr, pLineTmp->pName, iStrLen) )
            return pLineTmp;
    }

    return NULL;
}

struct stTree * CZGLanguage::findTreeName(char *pStr, unsigned int iStrLen)
{
    struct stTree *pTreeTmp = pstTreeList;

    for( ; pTreeTmp; pTreeTmp=pTreeTmp->next )
    {
        if( iStrLen == pTreeTmp->iNameLen && ! strncmp(pStr, pTreeTmp->pName, iStrLen) )
            return pTreeTmp;
    }

    return NULL;
}

struct stString * CZGLanguage::findAttrGroupName(char *pStr, unsigned int iStrLen)
{
    struct stString *pAttrGroupTmp = pstAttrGroupList;

    for( ; pAttrGroupTmp; pAttrGroupTmp=pAttrGroupTmp->next )
    {
        if( iStrLen == pAttrGroupTmp->iStrLen && ! strncmp(pStr, pAttrGroupTmp->pStr, iStrLen) )
            return pAttrGroupTmp;
    }

    return NULL;
}

bool CZGLanguage::completeAllDefInfo()
{
    // line
    struct stLine *pLineTmp = pstLineList;
    struct stLineLevel *pLineLevelTmp = NULL;

    for( ; pLineTmp; pLineTmp=pLineTmp->next )
    {
        pLineLevelTmp = pLineTmp->pstEleList;
        pLineTmp->pstEleList = NULL;

        while( pLineLevelTmp )
        {
            if( findLineName(pLineLevelTmp->pContentList->pStr,pLineLevelTmp->pContentList->iStrLen) )
            {
                pLineHead = pLineLevelTmp->pContentList->pStr;
                iLineNum = pLineLevelTmp->iLineNum;
                pText = pLineLevelTmp->pContentList->pStr + pLineLevelTmp->pContentList->iStrLen;

                return retErrInfo("Error : __ELE__ can not be a expression object !");
            }
            else if( findAttrGroupName(pLineLevelTmp->pContentList->pStr,pLineLevelTmp->pContentList->iStrLen) )
            {
                pLineHead = pLineLevelTmp->pContentList->pStr;
                iLineNum = pLineLevelTmp->iLineNum;
                pText = pLineLevelTmp->pContentList->pStr + pLineLevelTmp->pContentList->iStrLen;

                return retErrInfo("Error : __ELE__ can not be a attribute_group object !");
            }

            if( findTreeName(pLineLevelTmp->pContentList->pStr,pLineLevelTmp->pContentList->iStrLen) )
            {
				if( pLineLevelTmp->pTranPartList )
				{
                	pLineHead = pLineLevelTmp->pTranPartList->pStr - 3;   // 3 for >>>
                	iLineNum = pLineLevelTmp->iLineNum;
                	pText = pLineLevelTmp->pTranPartList->pStr + pLineLevelTmp->pTranPartList->iStrLen;

                	return retErrInfo("Tree object __ELE__ can not have Tran_part !");
				}

                struct stLineLevel *pTmp = pLineLevelTmp;
                pLineLevelTmp = pLineLevelTmp->next;
                pTmp->next = pLineTmp->pstEleList;
                pLineTmp->pstEleList = pTmp;
            }
            else if( findStrName(pLineLevelTmp->pContentList->pStr,pLineLevelTmp->pContentList->iStrLen) )
            {
                struct stLineLevel *pTmp = pLineLevelTmp;
                pLineLevelTmp = pLineLevelTmp->next;
                pTmp->next = pLineTmp->pstStrEleList;
                pLineTmp->pstStrEleList = pTmp;
            }
            else  // TYPE_CONT 常量
            {
                // 若不区分大小写，将操作符中的小写转成大写
                if( ! isCaseSensitive )
                {
                    char *pTmp = pLineLevelTmp->pContentList->pStr;
                    for(int i=0; i<pLineLevelTmp->pContentList->iStrLen; i ++ )
                    {
                        if( *pTmp >= 'a' && *pTmp <= 'z' )
                            *pTmp -= 32;

                        pTmp ++ ;
                    }
                }

                struct stLineLevel *pTmp = pLineLevelTmp;
                pLineLevelTmp = pLineLevelTmp->next;

                pTmp->next = pLineTmp->pstContEleList;
                pLineTmp->pstContEleList= pTmp;
            }
        }

        pLineLevelTmp = pLineTmp->pstOprList;
        for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
        {
            struct stString *pContentTmp = pLineLevelTmp->pContentList;
            for( ; pContentTmp; pContentTmp=pContentTmp->next )
            {
                if( findLineName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findTreeName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findStrName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findAttrGroupName(pContentTmp->pStr, pContentTmp->iStrLen) )
                {
                    pLineHead = pContentTmp->pStr;
                    iLineNum = pLineLevelTmp->iLineNum;
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;

                    return retErrInfo("__OPR__ content can not contain str, expression, path or attribute_group object !");
                }

                // 若不区分大小写，将操作符中的小写转成大写
                if( ! isCaseSensitive )
                {
                    char *pTmp = pContentTmp->pStr;
                    for(int i=0; i < pContentTmp->iStrLen; i ++ )
                    {
                        if( *pTmp >= 'a' && *pTmp <= 'z' )
                            *pTmp -= 32;

                        pTmp ++ ;
                    }
                }

            } // for
        } // for

        pLineLevelTmp = pLineTmp->pstBefList;
        for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
        {
            struct stString *pContentTmp = pLineLevelTmp->pContentList;
            for( ; pContentTmp; pContentTmp=pContentTmp->next )
            {
                if( findLineName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findTreeName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findStrName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findAttrGroupName(pContentTmp->pStr, pContentTmp->iStrLen) )
                {
                    pLineHead = pContentTmp->pStr;
                    iLineNum = pLineLevelTmp->iLineNum;
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;

                    return retErrInfo("__BEF__ content can not contain str, expression, path or attribute_group object !");
                }

                // 若不区分大小写，将操作符中的小写转成大写
                if( ! isCaseSensitive )
                {
                    char *pTmp = pContentTmp->pStr;
                    for(int i=0; i<pContentTmp->iStrLen; i ++ )
                    {
                        if( *pTmp >= 'a' && *pTmp <= 'z' )
                            *pTmp -= 32;

                        pTmp ++ ;
                    }
                }

            } // for( ; pContentTmp; pContentTmp=pContentTmp->next )
        } // for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )

        pLineLevelTmp = pLineTmp->pstAftList;
        for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
        {
            struct stString *pContentTmp = pLineLevelTmp->pContentList;
            for( ; pContentTmp; pContentTmp=pContentTmp->next )
            {
                if( findLineName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findTreeName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findStrName(pContentTmp->pStr, pContentTmp->iStrLen)
                 || findAttrGroupName(pContentTmp->pStr, pContentTmp->iStrLen) )
                {
                    pLineHead = pContentTmp->pStr;
                    iLineNum = pLineLevelTmp->iLineNum;
                    pText = pContentTmp->pStr + pContentTmp->iStrLen;

                    return retErrInfo("__AFT__ content can not contain str, expression, path or attribute_group object !");
                }

                // 若不区分大小写，将操作符中的小写转成大写
                if( ! isCaseSensitive )
                {
                    char *pTmp = pContentTmp->pStr;
                    for(int i=0; i<pContentTmp->iStrLen; i ++ )
                    {
                        if( *pTmp >= 'a' && *pTmp <= 'z' )
                            *pTmp -= 32;

                        pTmp ++ ;
                    }
                }

            } // for( ; pContentTmp; pContentTmp=pContentTmp->next )
        } // for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
    } // for( ; pLineTmp; pLineTmp=pLineTmp->next )

    ///////////////////////////////////////////////////////////

    // tree
    struct stTree *pTreeTmp = pstTreeList;
    struct stTreeCplLevel *pTreeLevelTmp = NULL;
    for( ; pTreeTmp; pTreeTmp=pTreeTmp->next )
    {
        pTreeLevelTmp = pTreeTmp->pstTreeCplLevels;
        for( ; pTreeLevelTmp; pTreeLevelTmp=pTreeLevelTmp->next )
        {
            if( ! strncmp("__ANY__", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_ANY;
            else if( ! strncmp("__\\b__", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_B;
            else if( ! strncmp("__\\t__", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_T;
            else if( ! strncmp("__\\n__", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_N;
            else if( ! strncmp("__BLANK__", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_BLANK;
            else if( findTreeName(pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_PATH;
            else if( findLineName(pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_EXPR;
            else if( findStrName(pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen) )
                pTreeLevelTmp->cType = TYPE_STR;
            else
            {
                pTreeLevelTmp->cType = TYPE_CONT;

                // 若不区分大小写，关键字统一转换成大写
                if( ! isCaseSensitive )
                {
                    char *pTmp = pTreeLevelTmp->pKeyword;
                    for(int i=0; i<pTreeLevelTmp->iKeywordLen; i ++ )
                    {
                        if( *pTmp >= 'a' && *pTmp <= 'z' )
                            *pTmp -= 32;

                        pTmp ++ ;

                    } // for
                } // if
            } // if
        } // for
    } // for

    return true;
}

// 根据类型，给并行+节点排序
/*****************************************************
bool CZGLanguage::orderByCkwflag4TreeLevel()
{
    struct stTree *pOneTree = pstTreeList;

    struct stTreeCplLevel *pTreeLevelHead = NULL;  // for | node
    struct stTreeCplLevel *pTreeLevelTail = NULL;  // for + node

    struct stString *pStringList4Order = NULL;
    struct stString *pKwInfo = NULL;

    for( ; pOneTree; pOneTree=pOneTree->next )
    {
        if( pOneTree->pstTreeCplLevels->next == NULL )
            continue ;

        pTreeLevelHead = pOneTree->pstTreeCplLevels;
        while( pTreeLevelHead && pTreeLevelHead->next )
        {
            if( pTreeLevelHead->next->cSplitFlag != '+' )
            {
                pTreeLevelHead = pTreeLevelHead->next;
                continue ;
            }

            pStringList4Order = getStringNode();
            memset(pStringList4Order, 0x00, sizeof(struct stString));
            pStringList4Order->pStr = pTreeLevelHead->pKeyword;
            pStringList4Order->iStrLen = pTreeLevelHead->iKeywordLen;
            pStringList4Order->cFlag = pTreeLevelHead->cType;
            pStringList4Order->iNum = pTreeLevelHead->iLineNum;

            pStringList4Order->pp = getStringNode();
            memset(pStringList4Order->pp, 0x00, sizeof(struct stString));
            ((struct stString *)(pStringList4Order->pp))->pStr = pTreeLevelHead->pOtherName;
            ((struct stString *)(pStringList4Order->pp))->iStrLen = pTreeLevelHead->iOtherNameLen;
            ((struct stString *)(pStringList4Order->pp))->iNum = pTreeLevelHead->iPriority;

            pTreeLevelTail = pTreeLevelHead->next;
            for( ; pTreeLevelTail; pTreeLevelTail=pTreeLevelTail->next )
            {
                if( pTreeLevelTail->cSplitFlag != '+' )
                    break ;

                pKwInfo = getStringNode();
                memset(pKwInfo, 0x00, sizeof(struct stString));
                pKwInfo->pStr = pTreeLevelTail->pKeyword;
                pKwInfo->iStrLen = pTreeLevelTail->iKeywordLen;
                pKwInfo->cFlag = pTreeLevelTail->cType;
                pKwInfo->iNum = pTreeLevelTail->iLineNum;
				
				// 20260113
				// pKwInfo->iNum = pTreeLevelTail->iLineNum;

                pKwInfo->pp = getStringNode();
                memset(pKwInfo->pp, 0x00, sizeof(struct stString));
                ((struct stString *)(pKwInfo->pp))->pStr = pTreeLevelTail->pOtherName;
                ((struct stString *)(pKwInfo->pp))->iStrLen = pTreeLevelTail->iOtherNameLen;
                ((struct stString *)(pKwInfo->pp))->iNum = pTreeLevelTail->iPriority;

                if( pTreeLevelTail->cType < pStringList4Order->cFlag
                 || (  pTreeLevelTail->cType == TYPE_CONT && pStringList4Order->cFlag == TYPE_CONT
                    && pTreeLevelTail->iKeywordLen >= pStringList4Order->iStrLen
                    )
                 || (pTreeLevelTail->cType != TYPE_CONT && pTreeLevelTail->cType == pStringList4Order->cFlag)
                )
                {
                    pKwInfo->next = pStringList4Order;
                    pStringList4Order = pKwInfo;

                    continue ;  // !!!
                }

                struct stString *pStringList4OrderTmp = pStringList4Order;
                for( ; pStringList4OrderTmp; pStringList4OrderTmp=pStringList4OrderTmp->next )
                {
                    if( pStringList4OrderTmp->next == NULL

                     || pTreeLevelTail->cType < pStringList4OrderTmp->next->cFlag

                     || (  pTreeLevelTail->cType == TYPE_CONT && pStringList4OrderTmp->next->cFlag == TYPE_CONT
                        && pTreeLevelTail->iKeywordLen >= pStringList4OrderTmp->next->iStrLen )

                     || ( pTreeLevelTail->cType != TYPE_CONT && pTreeLevelTail->cType == pStringList4OrderTmp->next->cFlag )
                    )
                    {
                        pKwInfo->next = pStringList4OrderTmp->next;
                        pStringList4OrderTmp->next = pKwInfo;

                        break ;
                    }
                }

            } // for( ; pTreeLevelTail; pTreeLevelTail=pTreeLevelTail->next )

            pKwInfo = pStringList4Order;
            for( ; pKwInfo; pKwInfo=pKwInfo->next )
            {
// printf("cType: %c\t", pKwInfo->cFlag);  // debug
// printStrForDebug("Kw", pKwInfo->pStr, pKwInfo->iStrLen);  // debug

                pTreeLevelHead->cType = pKwInfo->cFlag;
                pTreeLevelHead->pKeyword = pKwInfo->pStr;
                pTreeLevelHead->iKeywordLen = pKwInfo->iStrLen;
                pTreeLevelHead->iLineNum = pKwInfo->iNum;
                pTreeLevelHead->pOtherName = ((struct stString *)(pKwInfo->pp))->pStr;
                pTreeLevelHead->iOtherNameLen = ((struct stString *)(pKwInfo->pp))->iStrLen;
                pTreeLevelHead->iPriority = ((struct stString *)(pKwInfo->pp))->iNum;

                pTreeLevelHead = pTreeLevelHead->next;
            }
// printf("\n");  // debug

            freeStringList( & pStringList4Order);

        } // while( pTreeLevelHead->next )
    } // for( ; pOneTree; pOneTree=pOneTree->next )

    return true;
}
/********************************************************/
// 20260114 根据类型，给并行+节点排序
bool CZGLanguage::orderByCkwflag4TreeLevel()
{
    struct stTree *pOneTree = pstTreeList;

    struct stTreeCplLevel *pTreeLevelHead = NULL;  // for | node
    struct stTreeCplLevel *pTreeLevelTail = NULL;  // for + node

    struct stTreeCplLevel *pTreeLevel4Order = NULL;
    struct stTreeCplLevel *pKwInfo = NULL;

    for( ; pOneTree; pOneTree=pOneTree->next )
    {
        if( pOneTree->pstTreeCplLevels->next == NULL )
            continue ;

        pTreeLevelHead = pOneTree->pstTreeCplLevels;
        while( pTreeLevelHead && pTreeLevelHead->next )
        {
            if( pTreeLevelHead->next->cSplitFlag != '+' )
            {
                pTreeLevelHead = pTreeLevelHead->next;
                continue ;
            }

            pTreeLevel4Order = getTreeCplLevelNode();
            memset(pTreeLevel4Order, 0x00, sizeof(struct stTreeCplLevel));
			
			// 不能用 memcpy 全部复制 pTreeLevel4Order=pTreeLevelHead，有些参数不能移动
            pTreeLevel4Order->pKeyword       = pTreeLevelHead->pKeyword;
            pTreeLevel4Order->iKeywordLen    = pTreeLevelHead->iKeywordLen;
            pTreeLevel4Order->cType          = pTreeLevelHead->cType;
            pTreeLevel4Order->iAttrFlag      = pTreeLevelHead->iAttrFlag;
            pTreeLevel4Order->pStr4MatchRule = pTreeLevelHead->pStr4MatchRule;
			
			pTreeLevel4Order->iLineNum       = pTreeLevelHead->iLineNum;
			pTreeLevel4Order->pOtherName     = pTreeLevelHead->pOtherName;
            pTreeLevel4Order->iOtherNameLen  = pTreeLevelHead->iOtherNameLen;
            pTreeLevel4Order->iPriority      = pTreeLevelHead->iPriority;

            pTreeLevelTail = pTreeLevelHead->next;
            for( ; pTreeLevelTail; pTreeLevelTail=pTreeLevelTail->next )
            {
                if( pTreeLevelTail->cSplitFlag != '+' )
                    break ;

                pKwInfo = getTreeCplLevelNode();
                memset(pKwInfo, 0x00, sizeof(struct stTreeCplLevel));
				
				// 不能用 memcpy 全部复制 pTreeLevel4Order=pTreeLevelHead，有些参数不能移动
                pKwInfo->pKeyword       = pTreeLevelTail->pKeyword;
                pKwInfo->iKeywordLen    = pTreeLevelTail->iKeywordLen;
                pKwInfo->cType          = pTreeLevelTail->cType;
				pKwInfo->iAttrFlag      = pTreeLevelTail->iAttrFlag;
				pKwInfo->pStr4MatchRule = pTreeLevelTail->pStr4MatchRule;
				
                pKwInfo->iLineNum       = pTreeLevelTail->iLineNum;
                pKwInfo->pOtherName     = pTreeLevelTail->pOtherName;
                pKwInfo->iOtherNameLen  = pTreeLevelTail->iOtherNameLen;
                pKwInfo->iPriority      = pTreeLevelTail->iPriority;

                if( pTreeLevelTail->cType < pTreeLevel4Order->cType
                 || (  pTreeLevelTail->cType == TYPE_CONT && pTreeLevel4Order->cType == TYPE_CONT
                    && pTreeLevelTail->iKeywordLen >= pTreeLevel4Order->iKeywordLen
                    )
                 || (pTreeLevelTail->cType != TYPE_CONT && pTreeLevelTail->cType == pTreeLevel4Order->cType)
                )
                {
                    pKwInfo->next = pTreeLevel4Order;
                    pTreeLevel4Order = pKwInfo;

                    continue ;  // !!!
                }

                struct stTreeCplLevel *pTreeLevel4OrderTmp = pTreeLevel4Order;
                for( ; pTreeLevel4OrderTmp; pTreeLevel4OrderTmp=pTreeLevel4OrderTmp->next )
                {
                    if( pTreeLevel4OrderTmp->next == NULL

                     || pTreeLevelTail->cType < pTreeLevel4OrderTmp->next->cType

                     || (  pTreeLevelTail->cType == TYPE_CONT && pTreeLevel4OrderTmp->next->cType == TYPE_CONT
                        && pTreeLevelTail->iKeywordLen >= pTreeLevel4OrderTmp->next->iKeywordLen )

                     || ( pTreeLevelTail->cType != TYPE_CONT && pTreeLevelTail->cType == pTreeLevel4OrderTmp->next->cType )
                    )
                    {
                        pKwInfo->next = pTreeLevel4OrderTmp->next;
                        pTreeLevel4OrderTmp->next = pKwInfo;

                        break ;
                    }
                }

            } // for( ; pTreeLevelTail; pTreeLevelTail=pTreeLevelTail->next )

			// ATTR_CAN_SKIP 属性 和 |/\ 绑定，现在让它传染到其他 + 节点
			// 保存 |/\ 节点的 CAN_SKIP 属性
			unsigned int iCanSkipAttr = ATTR_CAN_SKIP & pTreeLevelHead->iAttrFlag;

            pKwInfo = pTreeLevel4Order;
            for( ; pKwInfo; pKwInfo=pKwInfo->next )
            {
// printf("cType: %c\t", pKwInfo->cFlag);  // debug
// printStrForDebug("Kw", pKwInfo->pStr, pKwInfo->iStrLen);  // debug

                pTreeLevelHead->pKeyword       = pKwInfo->pKeyword;
                pTreeLevelHead->iKeywordLen    = pKwInfo->iKeywordLen;
                pTreeLevelHead->cType          = pKwInfo->cType;
				pTreeLevelHead->iAttrFlag      = pKwInfo->iAttrFlag;
				pTreeLevelHead->iAttrFlag      |= iCanSkipAttr;           // 将 CAN_SKIP 属性 到传染到其他 + 节点
				pTreeLevelHead->pStr4MatchRule = pKwInfo->pStr4MatchRule;

                pTreeLevelHead->iLineNum       = pKwInfo->iLineNum;
                pTreeLevelHead->pOtherName     = pKwInfo->pOtherName;
                pTreeLevelHead->iOtherNameLen  = pKwInfo->iOtherNameLen;
                pTreeLevelHead->iPriority      = pKwInfo->iPriority;

                pTreeLevelHead = pTreeLevelHead->next;
            }
// printf("\n");  // debug

            freeTreeCplLevelList( & pTreeLevel4Order);

        } // while( pTreeLevelHead->next )
    } // for( ; pOneTree; pOneTree=pOneTree->next )

    return true;
}


bool CZGLanguage::printStrForDebug(const char *pHead, char *pStr, unsigned int iLen)
{
	if( pStr == NULL )
	{
    	printf("%s : \n", pHead);
		return true;
	}

    char *pBuf = (char *)malloc(iLen + 256);
    memset(pBuf, 0x00, iLen + 256);

    memcpy(pBuf, pStr, iLen);

    printf("%s : %s\n", pHead, pBuf);

    free(pBuf);
    return true;
}

bool CZGLanguage::initStart()
{
    iLineNum = 1;
    iLineHeadKgf = 0;
    iOneTabLen = 4;
	iLineNumBf4Tran = 0;

    iSeq = 0;
    iObjId = 0;

    pfOpf = NULL;

    pLgStr = NULL;
    iLgStrLen = 0;

	pstTranResult4OneLine = NULL;

    pLineComment = NULL;
    iLineCommentLen = 0;

    pLinesCommentStart = NULL;
    iLinesCommentStartLen = 0;
    pLinesCommentEnd = NULL;
    iLinesCommentEndLen = 0;

    initLogicSck(50);
    initStackSck(30);

    initStringPool(1000, 1000);
    initStrLevelPool(100, 100);
    initStrPool(100, 100);
    initLineLevelPool(100, 100);
    initLinePool(100, 100);
    initTreeCplLevelPool(100, 100);
    initTreeTranLevelPool(100, 100);
    initTreePool(100, 100);
    initPathPool(100, 100);
    initPathHeadPool(100, 100);
    initCompileInfoPool(1000, 1000);

    pstStrList = NULL;
    pstLineList = NULL;
    pstTreeList = NULL;
    pstPathHeadList = NULL;
    pstAttrGroupList = NULL;

    isCaseSensitive = true;
    isFuzzy = true;

    isTryKeepComment = true;
    pstCommentList = getStringNode();
	memset(pstCommentList, 0x00, sizeof(struct stString));
	pstCommentListTail = pstCommentList;

    cIndentType = INDENT_NULL;

    isDebug = false;
	pstDebugLimit = NULL;
	iCloseDebugTimes = 0;

	// 第一个缩进，长度为0
	pstIndentList4TranList = getStringNode();
	memset(pstIndentList4TranList, 0x00, sizeof(struct stString));

    // iSubLineCount = 0;
	pstSubLineCountList = NULL;

    cTreeLevelType = 0;
    cSplitFlag = '|';
    cSplitFlag4Tran4BfGoDown = '|';

    pPathHeadList4Any = NULL;
    pPathHeadList4B = NULL;
    pPathHeadList4T = NULL;
    pPathHeadList4N = NULL;
    pPathHeadList4Blank = NULL;
    pPathHeadList4Cont = NULL;
    pPathHeadList4Tree = NULL;
    pPathHeadList4Line = NULL;
    pPathHeadList4Str = NULL;

	pSuccessText4ObjPointHashTab = (struct stSuccessText4ObjPoint *)malloc(SUCCESS_TEXT_PATH_NUM * sizeof(struct stSuccessText4ObjPoint));
	memset(pSuccessText4ObjPointHashTab, 0x00, SUCCESS_TEXT_PATH_NUM * sizeof(struct stSuccessText4ObjPoint));

	pFailText4ObjPointHashTab = (struct stFailText4ObjPoint *)malloc(FAIL_TEXT_PATH_NUM * sizeof(struct stFailText4ObjPoint));
	memset(pFailText4ObjPointHashTab, 0x00, FAIL_TEXT_PATH_NUM * sizeof(struct stFailText4ObjPoint));

	// 第1个链表为 key-value
	pstExprRetHead = (struct stExprRetHead *)getStringNode();
	memset(pstExprRetHead, 0x00, sizeof(struct stExprRetHead));

	// 第2个链表开始往后为 list
	pstExprRetHead->next = (struct stExprRetHead *)getStringNode();
	memset(pstExprRetHead->next, 0x00, sizeof(struct stExprRetHead));

	// 用于解析部分，钻时缩进空格数的累加，第1层累计数为0，分隔符为 |
	pstIndentSum4GoNextTree4Cpl = getStringNode();
	memset(pstIndentSum4GoNextTree4Cpl, 0x00, sizeof(struct stString));
	pstIndentSum4GoNextTree4Cpl->cFlag = '|';

	iDoWithOneLineNodeCount = 0;
	iCount4SkipIndentTree = 0;

	pstIndentSum4GoNextTree4Cpl4GoBack = NULL;

	memset(&mLastTextInfo4Expr, 0x00, sizeof(struct stLastTextInfo4Expr));

    return true;
}

bool CZGLanguage::initEnd()
{
    dropLogicSck();
    dropStackSck();

    dropStringPool();
    dropStrLevelPool();
    dropStrPool();
    dropLineLevelPool();
    dropLinePool();
    dropTreeCplLevelPool();
    dropTreeTranLevelPool();
    dropTreePool();
    dropPathPool();
    dropPathHeadPool();
    dropCompileInfoPool();

    // munmap(pCfgMmp, iCfgFileSize);
	free(pCfgMmp);
    // close(iCfgFd);
	fclose(pCfgFd);

    // munmap(pCplMmp, iCplFileSize);
	free(pCplMmp);
    // close(iCplFd);
	fclose(pCplFd);

    // if( pLog )
    //    free(pLog);

    if( pfOpf )
        fclose(pfOpf);

	free(pSuccessText4ObjPointHashTab);
	free(pFailText4ObjPointHashTab);

    return true;
}


bool CZGLanguage::readSynFile(char *srcFile)
{
    extern char** environ;

    char *pEnvValue = NULL;
    char **env = environ;
    for( ; *env; *env ++ )
    {
        if( ! strncmp(*env, "ZGL_HOME", strlen("ZGL_HOME")) )
        {
            pEnvValue = *env + strlen("ZGL_HOME") + 1;
            break;
        }
    }

    if( ! pEnvValue )
    {
        printf("!!! warning !!! : Cannot not find environment value 'ZGL_HOME'\n");
        return false;
    }

    char mCfgFile[1024];
    // memset(mCfgFile, 0x00, sizeof(mCfgFile));

    if( srcFile == NULL )
        sprintf(mCfgFile,"%s/etc/ZGL.syn\0", pEnvValue);
    else
        sprintf(mCfgFile,"%s/etc/%s\0", pEnvValue, srcFile);

    /////////////////////////////////////////////

    iCfgFileSize = getFileSize(mCfgFile);
    if( iCfgFileSize == 0 )
    {
        printf("The file %s is empty !\n", mCfgFile);
        return false;
    }
    if( iCfgFileSize > 53687090 )
    {
        printf("The file %s is too large !\n", mCfgFile);
        return false;
    }

    /************
	iCfgFd = open(mCfgFile, O_RDONLY);
    if( iCfgFd == -1 )
    {
        printf("!!! warning !!! : Open the file '%s' failed !\n", mCfgFile);
        return false;
    }
	***********/
	pCfgFd = fopen(mCfgFile, "rb");
	if( pCfgFd == NULL )
    {
        printf("!!! warning !!! : Open the file '%s' failed !\n", mCfgFile);
        return false;
    }

    // void *srcStart = mmap(NULL, iCfgFileSize, PROT_READ, MAP_PRIVATE, iCfgFd, 0);
    /*************
	windows 没有 mmap 函数 
	// pCfgMmp = mmap(NULL, iCfgFileSize, PROT_WRITE, MAP_PRIVATE, iCfgFd, 0);
    if( pCfgMmp == MAP_FAILED )
    {
        printf("!!! warning !!! : Mmap the file '%s' failed !\n", mCfgFile);
        return false;
    }
	*******************/
	
	pCfgMmp = malloc(iCfgFileSize+4);
    if( pCfgMmp == NULL )
    {
        printf("!!! warning !!! : malloc failed !\n");
        return false;
    }
	memset(pCfgMmp+iCfgFileSize, 0x00, 4);
	
	// 将文件拷贝到内存中
	fread(pCfgMmp, 1, iCfgFileSize, pCfgFd);
	/***********
    size_t result = fread(pCfgMmp, 1, iCfgFileSize, pCfgFd);
    if( result != iCfgFileSize )
    {
		printf("!!! warning !!! : Reading file failed !\n");
        return false;
    }
	**********/
    

    ///////////////////////////////////////////////////////////////////

    pText = (char *)pCfgMmp;
    pLineHead = pText;
    if( ! makeSynTree() )
    {
        // munmap(pCfgMmp, iCfgFileSize);
        // close(iCfgFd);
        return false;
    }

    iLineNum = 1;    // 文件行数归 1

    return true;
}

bool CZGLanguage::makeSynTree()
{
    // 定义类型: __DEF_EXPR__ : L, __DEF_PATH__ : T, __DEF_SUB_PATH__ : t, __DEF_STR__ : S
    char cDefType = '\0';

    for( ; *pText; pText ++ )
    {
        if( *pText == ' ' || *pText == '\t' || *pText == '\r' )
            continue ;
 
        if( *pText == '\n' )
        {
            iLineNum ++ ;
            pLineHead = pText + 1;

/**********************************************
printf("-----------------------------\n");
char buffer[36];
memset(buffer, 0x00, sizeof(buffer));
strncpy(buffer, pLineHead, 35);
printf("%d : %s\n", iLineNum, buffer);
/**********************************************/

            continue ;
        }

        if( ! strncmp(pText, "__DEF_EXPR__ ", 13) || ! strncmp(pText, "__DEF_EXPR__\t", 13) )
        {
            cDefType = 'X';
            pText += 13;
        }
        else if( ! strncmp(pText, "__DEF_PATH__ ", 13) || ! strncmp(pText, "__DEF_PATH__\t", 13) )
        {
            cDefType = 'P';
            pText += 13;
        }
        else if( ! strncmp(pText,"__DEF_SUB_PATH__ ",17) || ! strncmp(pText,"__DEF_SUB_PATH__\t",17))
        {
            cDefType = 'p';
            pText += 17;
        }
        else if( ! strncmp(pText,"__DEF_STR__ ",12) || ! strncmp(pText,"__DEF_STR__\t",17))
        {
            cDefType = 'S';
            pText += 12;
        }
        else if( ! strncmp(pText, "__//__", 6) )
        {
            pText += 6;   // pass __//__
            for( ; *pText != '\n' && *pText != '\0'; pText ++ );
            pText -- ;
            continue;
        }
    	else if( ! strncmp(pText, "__/*__", 6) )
    	{
            pText += 6;   // pass __/*__
        	for( ; strncmp(pText, "__*/__", 6) && *pText != '\0'; pText ++ ) {
            	if( *pText == '\n' ) {
                	iLineNum ++ ;
                	pLineHead = pText;
            	}
        	}

        	// 最后一整行也注释掉
        	for( ; *pText != '\n' && *pText != '\0'; pText ++ );
        	pText ++ ;  // pass \n , \0
        	iLineNum ++ ;
            pLineHead = pText;

        	continue ;
    	}
        else if( ! strncmp(pText,"__DEF_CASE_SENSITIVE__ ",23) || ! strncmp(pText,"__DEF_CASE_SENSITIVE__\t",23))
        {
            pText += 23;   // pass __DEF_CASE_SENSITIVE__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( *pText == 'Y' || *pText == 'y' )
                isCaseSensitive = true;
            else if( *pText == 'N' || *pText == 'n' )
                isCaseSensitive = false;
            else
                return retErrInfo("Miss value 'Y' or 'N' after '__DEF_CASE_SENSITIVE__'");

/***************************************************
if( isCaseSensitive )
    printf("__DEF_CASE_SENSITIVE__ : Y\n");
else
    printf("__DEF_CASE_SENSITIVE__ : N\n");
/***************************************************/

            continue;
        }
        else if( ! strncmp(pText,"__DEF_DEBUG__ ",14) || ! strncmp(pText,"__DEF_DEBUG__\t",14))
        {
            pText += 14;   // pass __DEF_DEBUG__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( *pText == 'Y' || *pText == 'y' )
                isDebug = true;
            else if( *pText == 'N' || *pText == 'n' )
                isDebug = false;
            else
                return retErrInfo("Miss value 'Y' or 'N' after '__DEF_DEBUG__'");

/***************************************************
if( isDebug )
    printf("__DEF_DEBUG__ : Y\n");
else
    printf("__DEF_DEBUG__ : N\n");
***************************************************/

			// pText ++ ;   // pass Y/N   // 20251214

			if( ! readDebugLimit() )
				return false;

            continue;
        }
        else if( ! strncmp(pText,"__DEF_FUZZY__ ",14) || ! strncmp(pText,"__DEF_FUZZY__\t",14))
        {
            pText += 14;   // pass __DEF_FUZZY__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( *pText == 'Y' || *pText == 'y' )
                isFuzzy = true;
            else if( *pText == 'N' || *pText == 'n' )
                isFuzzy = false;
            else
                return retErrInfo("Miss value 'Y' or 'N' after '__DEF_FUZZY__'");

/***************************************************
if( isFuzzy )
    printf("__DEF_FUZZY__ : Y\n");
else
    printf("__DEF_FUZZY__ : N\n");
/***************************************************/

            continue;
        }
        else if( ! strncmp(pText,"__DEF_INDENT__ ",15) || ! strncmp(pText,"__DEF_INDENT__\t",15))
        {
            pText += 15;   // pass __DEF_INDENT__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( ! strncmp(pText, "NULL", 4) ) {
                cIndentType = 0;
                pText += 3;
            } else if( ! strncmp(pText, "COMPILER", 8) ) {
                cIndentType = 1;
                pText += 7;
            } else if( ! strncmp(pText, "TRANSLATOR", 10) ) {
                cIndentType = 2;
                pText += 9;
            } else if( ! strncmp(pText, "COMPILER_TRANSLATOR", 19) ) {
                cIndentType = 3;
                pText += 18;
            } else
                return retErrInfo("Miss value 'NULL', 'COMPILER', 'TRANSLATOR' or 'COMPILER_TRANSLATOR' after '__DEF_INDENT__'");

// printf("cIndentType = [%c]\n", cIndentType);  // debug

            continue;
        }
        else if( ! strncmp(pText,"__DEF_LINE_COMMENT__ ",21) || ! strncmp(pText,"__DEF_LINE_COMMENT__\t",21) )
        {
            pText += 21;   // pass __DEF_LINE_COMMEN__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

        	if( ! getVisibleStr() )
            	return false;

        	if( iLgStrLen == 0 )
                return retErrInfo("Miss content after '__DEF_LINE_COMMENT__'");

			pLineComment = pLgStr;
			iLineCommentLen = iLgStrLen;

			pLineComment4Tran = pLgStr;
			iLineCommentLen4Tran = iLgStrLen;

// printStrForDebug("__DEF_LINE_COMMENT__", pLineComment, iLineCommentLen);  // debug

			for( ; *pText == ' ' || *pText == '\t'; pText ++ );
			if( ! strncmp(pText, ">>>", 3) )
			{
				pText += 3;
				for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            	if( ! getVisibleStr() )
                	return false;

            	if( iLgStrLen == 0 )
                	return retErrInfo("Miss content after '>>>'");

            	pLineComment4Tran = pLgStr;
            	iLineCommentLen4Tran = iLgStrLen;
			}
			
			pText -- ;  // 避免循环时跳过 \n

            continue;
        }
        else if( ! strncmp(pText,"__DEF_LINES_COMMENT__ ",22) || ! strncmp(pText,"__DEF_LINES_COMMENT__\t",22) )
        {
            pText += 21;   // pass __DEF_LINES_COMMENT__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( ! getVisibleStr() )
                return false;

            if( iLgStrLen == 0 )
                return retErrInfo("Miss content after '__DEF_LINES_COMMENT__'");

            pLinesCommentStart = pLgStr;
            iLinesCommentStartLen = iLgStrLen;

            pLinesCommentStart4Tran = pLgStr;
            iLinesCommentStartLen4Tran = iLgStrLen;

// printStrForDebug("__DEF_LINES_COMMENT__ Start", pLinesCommentStart, iLinesCommentStartLen);  // debug

            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( ! getVisibleStr() )
                return false;

            if( iLgStrLen == 0 )
                return retErrInfo("Miss the second content for '__DEF_LINES_COMMENT__'");

            pLinesCommentEnd = pLgStr;
            iLinesCommentEndLen = iLgStrLen;

            pLinesCommentEnd4Tran = pLgStr;
            iLinesCommentEndLen4Tran = iLgStrLen;

// printStrForDebug("__DEF_LINES_COMMENT__ End  ", pLinesCommentEnd, iLinesCommentEndLen);  // debug

            for( ; *pText == ' ' || *pText == '\t'; pText ++ );
            if( ! strncmp(pText, ">>>", 3) )
            {
                pText += 3;
                for( ; *pText == ' ' || *pText == '\t'; pText ++ );

                if( ! getVisibleStr() )
                    return false;

                if( iLgStrLen == 0 )
                    return retErrInfo("Miss content after '>>>'");

                pLinesCommentStart4Tran = pLgStr;
                iLinesCommentStartLen4Tran = iLgStrLen;

				////////////////////////////////

                for( ; *pText == ' ' || *pText == '\t'; pText ++ );

                if( ! getVisibleStr() )
                    return false;

                if( iLgStrLen == 0 )
                	return retErrInfo("Miss the second content for '>>>'");

                pLinesCommentEnd4Tran = pLgStr;
                iLinesCommentEndLen4Tran = iLgStrLen;
            }

			pText -- ;  // 避免循环时跳过 \n

            continue;
        }
        else if( ! strncmp(pText,"__DEF_TRY_KEEP_COMMENT__ ",24) || ! strncmp(pText,"__DEF_TRY_KEEP_COMMENT__\t",24))
        {
            pText += 24;   // pass __DEF_TRY_KEEP_COMMENT__
            for( ; *pText == ' ' || *pText == '\t'; pText ++ );

            if( *pText == 'Y' || *pText == 'y' )
                isTryKeepComment = true;
            else if( *pText == 'N' || *pText == 'n' )
                isTryKeepComment = false;
            else
                return retErrInfo("Miss value 'Y' or 'N' after '__DEF_TRY_KEEP_COMMENT__'");

/***************************************************
if( isTryKeepComment )
    printf("__DEF_TRY_KEEP_COMMENT__ : Y\n");
else
    printf("__DEF_TRY_KEEP_COMMENT__ : N\n");
***************************************************/

            continue;
        }
        else if( ! strncmp(pText,"__DEF_ATTR_GROUP__ ",19) || ! strncmp(pText,"__DEF_ATTR_GROUP__\t",19))
        {
            cDefType = 'G';
            pText += 19;

        } else
            return retErrInfo("Syntax error !");
 
        for( ; *pText == ' ' || *pText == '\t'; pText ++ );

        if( ! getCmpStr() )
            return false;

        if( iLgStrLen == 0 )
        {
            if( cDefType == 'P' )
                return retErrInfo("Miss a name after __DEF_PATH__ !");
            else if( cDefType == 'p' )
                return retErrInfo("Miss a name after __DEF_SUB_PATH__ !");
            else if( cDefType == 'X' )
                return retErrInfo("Miss a name after __DEF_EXPR__ !");
            else if( cDefType == 'S' )
                return retErrInfo("Miss a name after __DEF_STR__ !");
            else if( cDefType == 'G' )
                return retErrInfo("Miss value after '__DEF_ATTR_GROUP__'");
            else
                return retErrInfo("Something error ?");
        }

        if( iLgStrLen < 5 || ( strncmp(pLgStr, "__", 2) || strncmp(pLgStr+iLgStrLen-2, "__", 2) ) )
            return retErrInfo("The name format must be '__xxx__' !");

        if( iLgStrLen > MAX_NAME_SZ )
            return retErrInfo("The name is too long !");

        if( isKeyword(pLgStr, iLgStrLen) )
        {
            pLineHead = pLgStr;
            pText = pLgStr + iLgStrLen;
            return retErrInfo("Key word can not be defined !");
        }

        if( findLineName(pLgStr, iLgStrLen) || findTreeName(pLgStr, iLgStrLen) 
         || findStrName(pLgStr, iLgStrLen) || findAttrGroupName(pLgStr, iLgStrLen) )
        {
            pLineHead = pLgStr;
            pText = pLgStr + iLgStrLen;
            return retErrInfo("This name cannot be redefined !");
        }

        for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );

        if( *pText == '\0' )
            return retErrInfo("Miss content at the end !");

        if( cDefType == 'X' ) {

            if( *pText != '\n' )
                return retErrInfo("Too many content after __DEF_EXPR__ !");

            pText ++ ;   // pass \n
            iLineNum ++ ;
            pLineHead = pText;

            if( ! createNewLine() )
                return false;

        } else if( cDefType == 'P' || cDefType == 'p' ) {

            // Get priority
            char *pInt = pText;
            unsigned int iIntLen = 0;
            unsigned int iPriority = 0;

            while(*pText >= '0' && *pText <= '9' ) //0~9
            {
                pText ++ ;
                iIntLen ++ ;
            }

            if( iIntLen > 7 )
                return retErrInfo("The priority is too long !");

            if( iIntLen > 0 )
            {
                char mBuf[12];
                memset(mBuf, 0x00, sizeof(mBuf));
                strncpy(mBuf, pInt, iIntLen);

                iPriority = atoi(mBuf);

                for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );  // pass kgf
            }

            ///////////////////////////////////////

            if( *pText != '\n' )
            {
                pText ++ ;
                return retErrInfo("Too many content after __DEF_PATH__ or __DEF_SUB_PATH__ !");
            }

            pText ++ ;   // pass \n
            iLineNum ++ ;
            pLineHead = pText;

            if( ! createNewTree(cDefType, iPriority) )
                return false;

        } else if( cDefType == 'S' ) {

            for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );  // pass kgf
            if( *pText != '\n' )
            {
                pText ++ ;
                return retErrInfo("Too many content after __DEF_STR__ !");
            }

            pText ++ ;   // pass \n
            iLineNum ++ ;
            pLineHead = pText;

            if( ! createNewStr() )
                return false;

        } else if( cDefType == 'G' ) {

            for( ; *pText==' ' || *pText=='\t' || *pText=='\r'; pText ++ );  // pass kgf
            if( *pText != '\n' )
            {
                pText ++ ;
                return retErrInfo("Too many content after __DEF_ATTR_GROUP__ !");
            }

            pText ++ ;   // pass \n
            iLineNum ++ ;
            pLineHead = pText;

            if( ! createNewAttrGroup() )
                return false;

        } else
            return retErrInfo("Something error 3 ???");
            
    } // for( ; *pText; pText ++ )

    if( ! completeAllDefInfo() )
        return false;

    if( ! orderByCkwflag4TreeLevel() )
        return false;

    if( ! makeCplTree2Paths() )
        return false;

    if( ! checkCplTreePaths() )
        return false;

    if( ! makeTranTree2Paths() )
        return false;

////////////////////////////////////////////////////////

/*********************************************
// print Str info
struct stStr *pStrTmp = pstStrList;
struct stStrLevel *pStrLevelTmp = NULL;
for( ; pStrTmp; pStrTmp=pStrTmp->next )
{
    printStrForDebug("Str name", pStrTmp->pName, pStrTmp->iNameLen);
    printf("pStr->iMinLen = [%d]\n", pStrTmp->iMinLen);
    printf("pStr->iMaxLen = [%d]\n", pStrTmp->iMaxLen);

    pStrLevelTmp = pStrTmp->pstStrLevelList;
    for( ; pStrLevelTmp; pStrLevelTmp=pStrLevelTmp->next )
    {
        printf("pStrLevel->iMinLen = [%d]\n", pStrLevelTmp->iMinLen);
        printf("pStrLevel->iMaxLen = [%d]\n", pStrLevelTmp->iMaxLen);

        for(int i=0; i<sizeof(pStrLevelTmp->mMap); i ++ )
        {
            if( pStrLevelTmp->mMap[i] )
                printf("%d : %c\n", i, i);
        }
    }

    printf("----------------------------------------\n");
}

*********************************************/


/*********************************************
// print Line info

struct stLine * pLineTmp = pstLineList;
struct stLineLevel *pLineLevelTmp = NULL;
struct stString *pContentTmp = NULL;
struct stString *pTranPartTmp = NULL;
for( ; pLineTmp; pLineTmp=pLineTmp->next )
{
    printStrForDebug("Line name", pLineTmp->pName, pLineTmp->iNameLen);

    if( pLineTmp->pSubLeft ) {
        printStrForDebug("Sub left", pLineTmp->pSubLeft, pLineTmp->iSubLeftLen);
        printStrForDebug("Sub right", pLineTmp->pSubRight, pLineTmp->iSubRightLen);
    } else {
        printf("Sub left : \n");
        printf("Sub right : \n");
    }

    struct stLineLevel * mPointer[4];
    mPointer[0] = pLineTmp->pstEleList;
    mPointer[1] = pLineTmp->pstOprList;
    mPointer[2] = pLineTmp->pstBefList;
    mPointer[3] = pLineTmp->pstAftList;
    mPointer[4] = pLineTmp->pstContEleList;

    printf("pstEleList : %p\n", pLineTmp->pstEleList);
    printf("pstOprList : %p\n", pLineTmp->pstOprList);
    printf("pstBefList : %p\n", pLineTmp->pstBefList);
    printf("pstAftList : %p\n", pLineTmp->pstAftList);
    printf("pstContEleList: %p\n", pLineTmp->pstContEleList);
    printf("pstContEleList: %p\n", pLineTmp->pstContEleList);

    for(int i=0 ; i<5; i ++ )
    {
        pLineLevelTmp = mPointer[i];

        for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
        {
            printf("--------------------------------\n");

            pContentTmp = pLineLevelTmp->pContentList;

            if( i == 0 )
                printStrForDebug("__ELE__", pContentTmp->pStr, pContentTmp->iStrLen);
            else if( i == 1 )
                printStrForDebug("__OPR__", pContentTmp->pStr, pContentTmp->iStrLen);
            else if( i == 2 )
                printStrForDebug("__BEF__", pContentTmp->pStr, pContentTmp->iStrLen);
            else if( i == 3 )
                printStrForDebug("__AFT__", pContentTmp->pStr, pContentTmp->iStrLen);
            else if( i == 4 )
                printStrForDebug("__CONT__", pContentTmp->pStr, pContentTmp->iStrLen);

            for( pContentTmp=pContentTmp->next; pContentTmp; pContentTmp=pContentTmp->next)
            {
                printStrForDebug("       ", pContentTmp->pStr, pContentTmp->iStrLen);
            }

            /////////////////////////////////

            if( ! pLineLevelTmp->pTranPartList )
                continue ;

            pTranPartTmp = pLineLevelTmp->pTranPartList;
            if( pTranPartTmp->iStrLen )
                printStrForDebug("\nTran", pTranPartTmp->pStr, pTranPartTmp->iStrLen);
            else
                printf("\nTran : [%c]\n", pTranPartTmp->cFlag);

            for( pTranPartTmp=pTranPartTmp->next; pTranPartTmp; pTranPartTmp=pTranPartTmp->next )
            {
                if( pTranPartTmp->iStrLen )
                    printStrForDebug("    ", pTranPartTmp->pStr, pTranPartTmp->iStrLen);
                else
                    printf("     : [%c]\n", pTranPartTmp->cFlag);
            }

        } // for( ; pLineLevelTmp; pLineLevelTmp=pLineLevelTmp->next )
    } // for(int i=0 ; i<4; i ++ )

    printf("==============================================\n\n");
}
*********************************************/

/*********************************************
// print Tree info

struct stTree *pTreeTmp = pstTreeList;
for( ; pTreeTmp; pTreeTmp=pTreeTmp->next )
{
    printStrForDebug("Tree name", pTreeTmp->pName, pTreeTmp->iNameLen);
    printf("Type : %c\n", pTreeTmp->cType);
    printf("iPathMaxX : %d\n", pTreeTmp->iPathMaxX);  // debug
    printf("iPriority: %d\n", pTreeTmp->iPriority);  // debug

    struct stTreeCplLevel * pTreeLevelTmp = pTreeTmp->pstTreeCplLevels;
    for( ; pTreeLevelTmp; pTreeLevelTmp=pTreeLevelTmp->next )
    {
        printf("-------------------------------------------\n");
        if( pTreeLevelTmp->pOtherName )
            printStrForDebug("Level other name", pTreeLevelTmp->pOtherName, pTreeLevelTmp->iOtherNameLen);
        else
            printf("Level other name : %d\n", pTreeLevelTmp->iOtherNameLen);

        printf("Priority : %d\n", pTreeLevelTmp->iPriority );
        printStrForDebug("Keyword", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen);
    }
    printf("============================================== Tree info\n\n");
}
*********************************************/

/***************************************************************/
// print path info
if( IF_PRINT )
{
struct stPathHead * pPathHeadTmp = pstPathHeadList;
for( ; pPathHeadTmp; pPathHeadTmp=pPathHeadTmp->next )
{
    printf("================================= path info\n");
    printStrForDebug("Tree name", pPathHeadTmp->pTree->pName, pPathHeadTmp->pTree->iNameLen);
    printf("PathY : %d\n", pPathHeadTmp->iPathY );

    printOnePath( pPathHeadTmp->pPathList, pPathHeadTmp->iPathY - 1 );
}
}
/***************************************************************/

/***************************************************************
// print attr group info
struct stString * pAttrGroupTmp = pstAttrGroupList;
for( ; pAttrGroupTmp; pAttrGroupTmp=pAttrGroupTmp->next )
{
    printf("=================================\n");
    printStrForDebug("Attr group name", pAttrGroupTmp->pStr, pAttrGroupTmp->iStrLen);
    printf("attr info: %x\n", pAttrGroupTmp->iNum);
}
printf("\n");
/***************************************************************/

    return true;
}

bool CZGLanguage::makeCplTree2Paths()
{
    struct stTree *pOneTree = pstTreeList;
    struct stTreeCplLevel * pTreeLevelTmp = NULL;

    for( ; pOneTree; pOneTree=pOneTree->next )
    {
        for(unsigned int iX=0; iX < pOneTree->iPathMaxX; iX ++ )
        {
            pTreeLevelTmp = pOneTree->pstTreeCplLevels;
            for( ; pTreeLevelTmp; pTreeLevelTmp=pTreeLevelTmp->next )
            {
                if( pTreeLevelTmp->pPathY[iX] == '1' || pTreeLevelTmp->pPathY[iX] == 'N' )
                    break ;
            }

            // 若此条线路无内容
            if( pTreeLevelTmp == NULL )
                continue ;

            struct stPathHead * pPathHeadNew = getPathHeadNode();
            memset(pPathHeadNew, 0x00, sizeof(struct stPathHead));
            pPathHeadNew->pTree = pOneTree;
            pPathHeadNew->iPathY = iX + 1;

            pPathHeadNew->next = pstPathHeadList;
            pstPathHeadList = pPathHeadNew;

            pPathHeadNew->pPathList = getPathNode();
            memset(pPathHeadNew->pPathList, 0x00, sizeof(struct stPath));
            pPathHeadNew->pPathList->pOneTreeCplLevel = pTreeLevelTmp;

            // 串行扩展
            struct stPath * pPath4Srl = pPathHeadNew->pPathList;
            // 并行扩展
            struct stPath * pPath4Prll = pPath4Srl;
            struct stPath * pPath4PrllHead = NULL;

            char cPrllFlag_1 = ' ';   // I J
            char cPrllFlag_N = ' ';   // M P

            for(pTreeLevelTmp=pTreeLevelTmp->next; pTreeLevelTmp; pTreeLevelTmp=pTreeLevelTmp->next)
            {
/*********************************
printf("pTreeLevelTmp ================ \n");
printf("%c : %c %d %d %d", pTreeLevelTmp->pPathY[iX]
						 , pTreeLevelTmp->cSplitFlag
						 , pTreeLevelTmp->cType
						 , pTreeLevelTmp->iIndent
						 , pTreeLevelTmp->iAttrFlag
						 );
printStrForDebug("", pTreeLevelTmp->pKeyword, pTreeLevelTmp->iKeywordLen);
*************************************/
				
/////////////////////////////
				
                // Pass 0 + + ....
                if( pTreeLevelTmp->pPathY[iX] == '0' )
                {
                    for( ; pTreeLevelTmp->next;  pTreeLevelTmp=pTreeLevelTmp->next )
                    {
                        if( pTreeLevelTmp->next->cSplitFlag == '+' )
                            continue;

                        break;
                    }
                    continue ;
                }

                struct stPath *pPathNew = getPathNode();
                memset(pPathNew, 0x00, sizeof(struct stPath));
                pPathNew->pOneTreeCplLevel = pTreeLevelTmp;

                if( pTreeLevelTmp->cSplitFlag == '|' || pTreeLevelTmp->cSplitFlag == '/' || pTreeLevelTmp->cSplitFlag == '\\' )
                {
                    // if + before , go to end
                    for( ; pPath4Srl->nextNode;  pPath4Srl=pPath4Srl->nextNode );

                    if( pTreeLevelTmp->pPathY[iX] == '1' 
                     || pTreeLevelTmp->pPathY[iX] == 'N'
                     || pTreeLevelTmp->pPathY[iX] == 'e'
                     || pTreeLevelTmp->pPathY[iX] == 'E' )
                    {
                        // 加 行 分支
                        for( ; pPath4Prll->next; pPath4Prll=pPath4Prll->next );

                        pPath4Prll->next = pPathNew;
                        pPath4Prll = pPath4Prll->next;
                        pPath4Srl = pPath4Prll;
                    }
                    else if( pTreeLevelTmp->pPathY[iX] == '+' )
                    {
                        char cPathY = pPath4Prll->pOneTreeCplLevel->pPathY[iX];
                        if( cPathY == '1' )
                        {
                            if( cPrllFlag_1 == 'I' )
                                cPrllFlag_1 = 'J';
                            else
                                cPrllFlag_1 = 'I';

                            pPath4Prll->pOneTreeCplLevel->pPathY[iX] = cPrllFlag_1;
                            pPathNew->pOneTreeCplLevel->pPathY[iX] = cPrllFlag_1;
                            pPath4PrllHead = pPath4Prll;
                        }
                        else if( cPathY == 'N' )
                        {
                            if( cPrllFlag_N == 'M' )
                                cPrllFlag_N = 'P';
                            else
                                cPrllFlag_N = 'M';

                            pPath4Prll->pOneTreeCplLevel->pPathY[iX] = cPrllFlag_N;
                            pPathNew->pOneTreeCplLevel->pPathY[iX] = cPrllFlag_N;
                            pPath4PrllHead = pPath4Prll;
                        }
                        else if( cPathY == 'I' || cPathY == 'J' || cPathY == 'M' || cPathY == 'P' )
                        {
                            pPathNew->pOneTreeCplLevel->pPathY[iX] = cPathY;
                        }

                        // 加 行 分支
                        if( pPathNew->pOneTreeCplLevel->cType < pPath4PrllHead->pOneTreeCplLevel->cType
                         || (  pPathNew->pOneTreeCplLevel->cType == TYPE_CONT
                            && pPath4PrllHead->pOneTreeCplLevel->cType == TYPE_CONT
                            && pPathNew->pOneTreeCplLevel->iKeywordLen >= pPath4PrllHead->pOneTreeCplLevel->iKeywordLen
                            )
                         || (  pPathNew->pOneTreeCplLevel->cType != TYPE_CONT
                            && pPathNew->pOneTreeCplLevel->cType == pPath4PrllHead->pOneTreeCplLevel->cType )
                        )
                        {
                            if( pPath4PrllHead == pPathHeadNew->pPathList )
                            {
                                pPathNew->next = pPathHeadNew->pPathList;
                                pPathHeadNew->pPathList = pPathNew;
                                pPath4PrllHead = pPathHeadNew->pPathList;
                            }
                            else
                            {
                                struct stPath *pPathTmp = pPathHeadNew->pPathList;
                                for( ; pPathTmp->next != pPath4PrllHead; pPathTmp=pPathTmp->next );
                                pPathNew->next = pPathTmp->next;
                                pPathTmp->next = pPathNew;
                                pPath4PrllHead = pPathTmp->next;
                            }
                        }
                        else
                        {
                            struct stPath *pPathTmp = pPath4PrllHead;
                            for( ; pPathTmp; pPathTmp=pPathTmp->next )
                            {
                                if( pPathTmp->next == NULL
                                 || pPathNew->pOneTreeCplLevel->cType < pPathTmp->next->pOneTreeCplLevel->cType
                                 || (  pPathNew->pOneTreeCplLevel->cType == TYPE_CONT
                                    && pPathTmp->next->pOneTreeCplLevel->cType == TYPE_CONT
                                    && pPathNew->pOneTreeCplLevel->iKeywordLen >= pPathTmp->next->pOneTreeCplLevel->iKeywordLen
                                    )
                                 || (  pPathNew->pOneTreeCplLevel->cType != TYPE_CONT
                                    && pPathNew->pOneTreeCplLevel->cType == pPathTmp->next->pOneTreeCplLevel->cType )
                                )
                                {
                                    pPathNew->next = pPathTmp->next;
                                    pPathTmp->next = pPathNew;

                                    break ;
                                }
                            } // for
                        } // if

                        pPath4Srl = pPathNew;
                    }
                    else if( pTreeLevelTmp->pPathY[iX] == ' ' )
                    {
                        pPath4Srl->nextNode = pPathNew;
                        pPath4Srl = pPath4Srl->nextNode;
                    }
                    else
                        return retErrInfo("Something error 4 ???");
                }
                else if( pTreeLevelTmp->cSplitFlag == '+' )
                {
                    pPath4Srl->nextNode = pPathNew;
                    pPath4Srl = pPath4Srl->nextNode;

                } else
                    return retErrInfo("Something error 5 ???");

            } // for(pTreeLevelTmp=pTreeLevelTmp->next; pTreeLevelTmp; pTreeLevelTmp=pTreeLevelTmp->next)

/***************************************************************
printf("=================================\n");
printStrForDebug("Tree name", pPathHeadNew->pTree->pName, pPathHeadNew->pTree->iNameLen);
printf("PathY : %d\n", pPathHeadNew->iPathY );

struct stPath * pPathTmp = pPathHeadNew->pPathList;
for( ; pPathTmp; pPathTmp=pPathTmp->next )
{
    struct stPath * pPathTmp2 = pPathTmp;
    for( ; pPathTmp2; pPathTmp2=pPathTmp2->nextNode )
    {
        printf("%c : %d", *(pPathTmp2->pOneTreeCplLevel->pPathY + pPathHeadNew->iPathY-1), pPathTmp2->pOneTreeCplLevel->cType);
        printStrForDebug("", pPathTmp2->pOneTreeCplLevel->pKeyword, pPathTmp2->pOneTreeCplLevel->iKeywordLen);
    }
    printf("--------------------------------\n");
}
***************************************************************/

            ////////////////////////////////////////////
            // 形成语法树
            ////////////////////////////////////////////

            struct stPath * pPath4PrllBefore = pPathHeadNew->pPathList;
            pPath4Prll = pPath4PrllBefore;

            while( true )
            {
                char cPathY = *(pPath4Prll->pOneTreeCplLevel->pPathY + pPathHeadNew->iPathY - 1); 

                pPath4Prll = pPath4Prll->next;
                if( pPath4Prll == NULL )
                    break ;

                if( cPathY == 'I' || cPathY == 'J' || cPathY == 'M' || cPathY == 'P' )
                {
                    for( ; pPath4Prll; pPath4Prll=pPath4Prll->next )
                    {
                        if( cPathY == *(pPath4Prll->pOneTreeCplLevel->pPathY + pPathHeadNew->iPathY - 1) )
                            continue ;
                        else
                            break ;
                    }

                    if( pPath4Prll == NULL )
                        break ;

                    for( ; pPath4PrllBefore->next != pPath4Prll; pPath4PrllBefore=pPath4PrllBefore->next )
                    {
                        pPath4Srl = pPath4PrllBefore;
                        for( ; pPath4Srl->nextNode; pPath4Srl=pPath4Srl->nextNode );
                        pPath4Srl->nextNode = pPath4Prll;
                    }

                    pPath4Srl = pPath4PrllBefore;
                    for( ; pPath4Srl->nextNode; pPath4Srl=pPath4Srl->nextNode );
                    pPath4Srl->nextNode = pPath4Prll;

                } else {
                    pPath4Srl = pPath4PrllBefore;
                    for( ; pPath4Srl->nextNode; pPath4Srl=pPath4Srl->nextNode );
                    pPath4Srl->nextNode = pPath4Prll;
                }

                pPath4PrllBefore->next = NULL;
                pPath4PrllBefore = pPath4Prll;

            } // while( true )
        } // for(int iX=0; iX < pOneTree->iPathMaxX; iX ++ )
    } // for( ; pOneTree; pOneTree=pOneTree->next )

    // 给各完整语法路径再排序
    struct stPathHead * pPathHeadTail = pstPathHeadList->next;
    struct stPathHead * pPathHeadAdd = NULL;
    pstPathHeadList->next = NULL;
    while( pPathHeadTail )
    {
        pPathHeadAdd = pPathHeadTail;
        pPathHeadTail = pPathHeadTail->next;
        pPathHeadAdd->next = NULL;

        if( pPathHeadAdd->pPathList->pOneTreeCplLevel->cType < pstPathHeadList->pPathList->pOneTreeCplLevel->cType
         || (  pPathHeadAdd->pPathList->pOneTreeCplLevel->cType == TYPE_CONT
            && pstPathHeadList->pPathList->pOneTreeCplLevel->cType == TYPE_CONT
            && pPathHeadAdd->pPathList->pOneTreeCplLevel->iKeywordLen >= pstPathHeadList->pPathList->pOneTreeCplLevel->iKeywordLen
            )
         || (  pPathHeadAdd->pPathList->pOneTreeCplLevel->cType != TYPE_CONT
            && pPathHeadAdd->pPathList->pOneTreeCplLevel->cType == pstPathHeadList->pPathList->pOneTreeCplLevel->cType
            )
        )
        {
            pPathHeadAdd->next = pstPathHeadList;
            pstPathHeadList = pPathHeadAdd;

            continue ;  // !!!
        }

        struct stPathHead * pPathHeadTmp = pstPathHeadList;
        for( ; pPathHeadTmp; pPathHeadTmp=pPathHeadTmp->next )
        {
            if( pPathHeadTmp->next == NULL
             || pPathHeadAdd->pPathList->pOneTreeCplLevel->cType < pPathHeadTmp->next->pPathList->pOneTreeCplLevel->cType
             || (  pPathHeadAdd->pPathList->pOneTreeCplLevel->cType == TYPE_CONT
                && pPathHeadTmp->next->pPathList->pOneTreeCplLevel->cType == TYPE_CONT
                && pPathHeadAdd->pPathList->pOneTreeCplLevel->iKeywordLen >= pPathHeadTmp->next->pPathList->pOneTreeCplLevel->iKeywordLen
                )
             || (  pPathHeadAdd->pPathList->pOneTreeCplLevel->cType != TYPE_CONT
                && pPathHeadAdd->pPathList->pOneTreeCplLevel->cType == pPathHeadTmp->next->pPathList->pOneTreeCplLevel->cType 
                )
            )
            {
                pPathHeadAdd->next = pPathHeadTmp->next;
                pPathHeadTmp->next = pPathHeadAdd;

                break ;  // !!!
            }
        }
        
    } // while( pPathHeadTail )

    return true;
}

bool CZGLanguage::makeTranTree2Paths()
{
// printf("\nmakeTranTree2Paths !!!!!!!!!!!!!!!!!!!!!!!!!!!\n");  // debug

    struct stTree *pOneTree = pstTreeList;
    struct stTreeTranLevel * pTreeTranLevelHead = NULL;
    struct stTreeTranLevel * pTreeTranLevelTmp = NULL;

    for( ; pOneTree; pOneTree=pOneTree->next )
    {
// printStrForDebug("pOneTree->pName", pOneTree->pName, pOneTree->iNameLen);
// printf("pOneTree->pstTreeTranLevels = [%p]\n", pOneTree->pstTreeTranLevels);  // debug

        if( ! pOneTree->pstTreeTranLevels )
            continue ;

        pTreeTranLevelHead = pOneTree->pstTreeTranLevels;
        pTreeTranLevelTmp = pOneTree->pstTreeTranLevels;

        unsigned int iX = 0;
        for( ; iX < pOneTree->iPathMaxX && pTreeTranLevelTmp->pPathY[iX] == ' '; iX ++ );

        while( pTreeTranLevelTmp )
        {
// printf("------------------------------- pTreeTranLevelTmp [%d] -----------------------\n", iX);
            struct stPathHead * pPathHeadNew = pstPathHeadList;
            for( ; pPathHeadNew; pPathHeadNew=pPathHeadNew->next )
            {
                if( pPathHeadNew->pTree == pOneTree && pPathHeadNew->iPathY == iX + 1 )
                    break ;
            }

            // 若重复定义，报错
            if( pPathHeadNew->pTranPathList )
            {
                pText = pTreeTranLevelTmp->pPathY + iX + 1;
                iLineNum = pTreeTranLevelTmp->iLineNum;
                
                for(pLineHead=pText; *pLineHead != '\n'; pLineHead -- );
                pLineHead ++ ;

                return retErrInfo("The transformation path is redefined here !");
            }

            pPathHeadNew->pTranPathList = getPathNode();
            memset(pPathHeadNew->pTranPathList, 0x00, sizeof(struct stPath));
            pPathHeadNew->pTranPathList->pOneTreeTranLevel = pTreeTranLevelTmp;

            // 串行扩展
            struct stPath * pPath4Srl = pPathHeadNew->pTranPathList;
            // 并行扩展
            struct stPath * pPath4Prll = pPath4Srl;
            struct stPath * pPath4PrllHead = NULL;

            char cPrllFlag_1 = ' ';   // I J
            char cPrllFlag_N = ' ';   // M P

            for( pTreeTranLevelTmp=pTreeTranLevelTmp->next; pTreeTranLevelTmp; pTreeTranLevelTmp=pTreeTranLevelTmp->next)
            {
// printf("pTreeTranLevelTmp = [%d][%d][%d] !!!!!!!!!!!!!!!!!!!!!!!\n", pTreeTranLevelTmp->isFirstNodeOfNewTran, iX, pOneTree->iPathMaxX);
// printStrForDebug("pTreeTranLevelTmp->pPathY", pTreeTranLevelTmp->pPathY, pOneTree->iPathMaxX);

                // 新的转换部分
                if( pTreeTranLevelTmp->isFirstNodeOfNewTran )
                {
                    for( iX ++ ; iX < pOneTree->iPathMaxX && pTreeTranLevelHead->pPathY[iX] == ' '; iX ++ );

					// 若此转换部分并行路径已经解析完
                    if( iX == pOneTree->iPathMaxX ) {
        				for( iX = 0; iX < pOneTree->iPathMaxX && pTreeTranLevelTmp->pPathY[iX] == ' '; iX ++ );
                        pTreeTranLevelHead = pTreeTranLevelTmp;
                    } else
                        pTreeTranLevelTmp = pTreeTranLevelHead;

                    break ;
                }

                // Pass 0 + + ....
                if( pTreeTranLevelTmp->pPathY[iX] == '0' )
                {
                    for( ; pTreeTranLevelTmp->next;  pTreeTranLevelTmp=pTreeTranLevelTmp->next )
                    {
                        if( pTreeTranLevelTmp->next->cSplitFlag == '+' )
                            continue;

                        break;
                    }
                    continue ;
                }

                struct stPath *pPathNew = getPathNode();
                memset(pPathNew, 0x00, sizeof(struct stPath));
                pPathNew->pOneTreeTranLevel = pTreeTranLevelTmp;

                if( pTreeTranLevelTmp->cSplitFlag == '|' 
                 || pTreeTranLevelTmp->cSplitFlag == '/' 
                 || pTreeTranLevelTmp->cSplitFlag == '\\' )
                {
                    // if + before , go to end
                    for( ; pPath4Srl->nextNode;  pPath4Srl=pPath4Srl->nextNode );

                    if( pTreeTranLevelTmp->pPathY[iX] == '1' 
                     || pTreeTranLevelTmp->pPathY[iX] == 'N'
                     || pTreeTranLevelTmp->pPathY[iX] == 'n'
                     || pTreeTranLevelTmp->pPathY[iX] == '*'
                     || pTreeTranLevelTmp->pPathY[iX] == 'e' )  // 20230305
                    {
                        // 加 行 分支
                        for( ; pPath4Prll->next; pPath4Prll=pPath4Prll->next );

                        pPath4Prll->next = pPathNew;
                        pPath4Prll = pPath4Prll->next;
                        pPath4Srl = pPath4Prll;
                    }
                    else if( pTreeTranLevelTmp->pPathY[iX] == ' ' )
                    {
                        pPath4Srl->nextNode = pPathNew;
                        pPath4Srl = pPath4Srl->nextNode;
                    }
                    else
                        return retErrInfo("Something error 6 ???");
                }
                else if( pTreeTranLevelTmp->cSplitFlag == '+' )
                {
                    pPath4Srl->nextNode = pPathNew;
                    pPath4Srl = pPath4Srl->nextNode;

                } else
                    return retErrInfo("Something error 7 ???");

            } // for(pTreeTranLevelTmp=pTreeTranLevelTmp->next; pTreeTranLevelTmp; pTreeTranLevelTmp=pTreeTranLevelTmp->next)

/***************************************************************/
if( IF_PRINT )
{
printf("================================= pTranPathList ===========================\n");
printStrForDebug("Tree name", pPathHeadNew->pTree->pName, pPathHeadNew->pTree->iNameLen);
printf("PathY : %d\n", pPathHeadNew->iPathY );

struct stPath * pPathTmp = pPathHeadNew->pTranPathList;
for( ; pPathTmp; pPathTmp=pPathTmp->next )
{
    struct stPath * pPathTmp2 = pPathTmp;
    for( ; pPathTmp2; pPathTmp2=pPathTmp2->nextNode )
    {
        printf("Path node : [%c]\n", *(pPathTmp2->pOneTreeTranLevel->pPathY + pPathHeadNew->iPathY-1));
        printStrForDebug("", pPathTmp2->pOneTreeTranLevel->pKeyword, pPathTmp2->pOneTreeTranLevel->iKeywordLen);
    }
    printf("--------------------------------\n");
}
}
/*************************************************************/

            ////////////////////////////////////////////
            // 形成语法树
            ////////////////////////////////////////////

            struct stPath * pPath4PrllBefore = pPathHeadNew->pTranPathList;
            pPath4Prll = pPath4PrllBefore;

            while( true )
            {
                char cPathY = *(pPath4Prll->pOneTreeTranLevel->pPathY + pPathHeadNew->iPathY - 1); 

                pPath4Prll = pPath4Prll->next;
                if( pPath4Prll == NULL )
                    break ;

                if( cPathY == 'I' || cPathY == 'J' || cPathY == 'M' || cPathY == 'P' )
                {
                    for( ; pPath4Prll; pPath4Prll=pPath4Prll->next )
                    {
                        if( cPathY == *(pPath4Prll->pOneTreeTranLevel->pPathY + pPathHeadNew->iPathY - 1) )
                            continue ;
                        else
                            break ;
                    }

                    if( pPath4Prll == NULL )
                        break ;

                    for( ; pPath4PrllBefore->next != pPath4Prll; pPath4PrllBefore=pPath4PrllBefore->next )
                    {
                        pPath4Srl = pPath4PrllBefore;
                        for( ; pPath4Srl->nextNode; pPath4Srl=pPath4Srl->nextNode );
                        pPath4Srl->nextNode = pPath4Prll;
                    }

                    pPath4Srl = pPath4PrllBefore;
                    for( ; pPath4Srl->nextNode; pPath4Srl=pPath4Srl->nextNode );
                    pPath4Srl->nextNode = pPath4Prll;

                } else {
                    pPath4Srl = pPath4PrllBefore;
                    for( ; pPath4Srl->nextNode; pPath4Srl=pPath4Srl->nextNode );
                    pPath4Srl->nextNode = pPath4Prll;
                }

                pPath4PrllBefore->next = NULL;
                pPath4PrllBefore = pPath4Prll;

            } // while( true )

			// 检查是否还有并行路径未解析
			if( ! pTreeTranLevelTmp )
			{
            	for( iX ++ ; iX < pOneTree->iPathMaxX && pTreeTranLevelHead->pPathY[iX] == ' '; iX ++ );
                if( iX < pOneTree->iPathMaxX )
                	pTreeTranLevelTmp = pTreeTranLevelHead;
			}

        } // while( pTreeTranLevelTmp )
    } // for( ; pOneTree; pOneTree=pOneTree->next )

    return true;
}

// 串行 优先
bool CZGLanguage::printOnePath(struct stPath *pPath, unsigned int iPathY)
{
    printf("%c : %c %d %d %d", *(pPath->pOneTreeCplLevel->pPathY + iPathY)
	                         , pPath->pOneTreeCplLevel->cSplitFlag
	                         , pPath->pOneTreeCplLevel->cType
							 , pPath->pOneTreeCplLevel->iIndent
							 , pPath->pOneTreeCplLevel->iAttrFlag
							 );
    printStrForDebug("", pPath->pOneTreeCplLevel->pKeyword, pPath->pOneTreeCplLevel->iKeywordLen);
    // printStrForDebug("    OtherName", pPath->pOneTreeCplLevel->pOtherName, pPath->pOneTreeCplLevel->iOtherNameLen);

    if( pPath->nextNode )
        printOnePath(pPath->nextNode, iPathY);

    if( pPath->next )
    {
        printf("---------------\n");
        printOnePath(pPath->next, iPathY);
    }

    return true;
}

// 检查 LINE ANY 对象后面的结束符
bool CZGLanguage::checkEndOfLine_Any(struct stPathHead *pThisPathHead, struct stPath *pPath, unsigned int iPathY)
{
    char cKeywordEnd = *(pPath->pOneTreeCplLevel->pKeyword + pPath->pOneTreeCplLevel->iKeywordLen);
    char cTreeNameEnd = *(pThisPathHead->pTree->pName + pThisPathHead->pTree->iNameLen);
    *(pPath->pOneTreeCplLevel->pKeyword + pPath->pOneTreeCplLevel->iKeywordLen) = '\0';
    *(pThisPathHead->pTree->pName + pThisPathHead->pTree->iNameLen) = '\0';

    // if( pPath->pOneTreeCplLevel->cType == 'X' )
    if( pPath->pOneTreeCplLevel->cType == TYPE_EXPR || pPath->pOneTreeCplLevel->cType == TYPE_ANY )
    {
        if( pPath->pOneTreeCplLevel->cType == TYPE_ANY )
            pPath->pOneTreeCplLevel->cSplitFlag = '/';

        struct stPath *pPathTmp = pPath;
        for( ; pPathTmp->nextNode && pPathTmp->nextNode->pOneTreeCplLevel->cSplitFlag == '+'; pPathTmp=pPathTmp->nextNode )
        {
            if( pPath->pOneTreeCplLevel->cType == TYPE_ANY && pPathTmp->nextNode->pOneTreeCplLevel->cType != TYPE_CONT )
            {
                printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The '+' object with __ANY__ must be a constant : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);
                return false;
            }
        }

        if( pPathTmp->nextNode
         && (  *(pPathTmp->nextNode->pOneTreeCplLevel->pPathY + iPathY) == 'e'
            || *(pPathTmp->nextNode->pOneTreeCplLevel->pPathY + iPathY) == 'E' )
        )
        {
            pPathTmp = pPathTmp->nextNode;
            for( ; pPathTmp->nextNode && pPathTmp->nextNode->pOneTreeCplLevel->cSplitFlag == '+'
                 ; pPathTmp=pPathTmp->nextNode);
        }

/******************************************
        if( pPathTmp->nextNode == NULL )
        {
            if( pPath->pOneTreeCplLevel->cType == TYPE_EXPR )
               printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| Miss the end for the line object '%s' : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, pPath->pOneTreeCplLevel->pKeyword, iPathY+1, pThisPathHead->pTree->pName);
            else if( pPath->pOneTreeCplLevel->cType == TYPE_ANY )
                printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| Miss the end for the __ANY__ object : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);

            return false;
        }
******************************************/
        if( pPathTmp->nextNode == NULL && pPath->pOneTreeCplLevel->cType == TYPE_ANY )
		{
            printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| Miss the end for the __ANY__ object : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);
            return false;
		}
        else
        {
            // 检查 LINE 对象后面的结束符 类型
            struct stPath *pPath4Next = pPathTmp->nextNode;
            for( ; pPath4Next; pPath4Next=pPath4Next->next )
            {
                struct stPath *pPath4NextNode = pPath4Next;
                for( ; pPath4NextNode; pPath4NextNode=pPath4NextNode->nextNode )
                {
/******************************************************
                    if( pPath4NextNode->pOneTreeCplLevel->cType == TYPE_PATH || pPath4NextNode->pOneTreeCplLevel->cType == TYPE_EXPR )
                    {
                        if( pPath->pOneTreeCplLevel->cType == TYPE_EXPR )
                            printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The end for the line object '%s' can not be tree or line : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, pPath->pOneTreeCplLevel->pKeyword, iPathY+1, pThisPathHead->pTree->pName);
                        else if( pPath->pOneTreeCplLevel->cType == TYPE_ANY )
                            printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The end for the __ANY__ object can not be tree or line : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);

                        return false;
                    }

                    if( pPath4NextNode->pOneTreeCplLevel->cType == TYPE_STR )
                    {
                        if( pPath->pOneTreeCplLevel->cType == TYPE_EXPR )
                            printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The end for the line object '%s' can not be STR object : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, pPath->pOneTreeCplLevel->pKeyword, iPathY+1, pThisPathHead->pTree->pName);
                        else if( pPath->pOneTreeCplLevel->cType == TYPE_ANY )
                            printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The end for the __ANY__ object can not be STR object: At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);

                        return false;
                    }
******************************************************/

                    if( ( pPath4NextNode->pOneTreeCplLevel->cType == TYPE_PATH || pPath4NextNode->pOneTreeCplLevel->cType == TYPE_EXPR )
                     && pPath->pOneTreeCplLevel->cType == TYPE_ANY )
                    {
                        printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The end for the __ANY__ object can not be tree or line : At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);
                        return false;
                    }

                    if( pPath4NextNode->pOneTreeCplLevel->cType == TYPE_STR && pPath->pOneTreeCplLevel->cType == TYPE_ANY )
                    {
                        printf("!!! Syntax file ERROR !!!\n|1| Line %d\n|2| The end for the __ANY__ object can not be STR object: At the path[%d] of tree '%s'\n", pPath->pOneTreeCplLevel->iLineNum, iPathY+1, pThisPathHead->pTree->pName);
                        return false;
                    }

                    if( pPath4NextNode->nextNode == NULL || pPath4NextNode->nextNode->pOneTreeCplLevel->cSplitFlag != '+' )
                        break ;

                } // for( ; pPath4NextNode; pPath4NextNode=pPath4NextNode->next )
            } // for( ; pPath4Next; pPath4Next=pPath4Next->next )
        } // if( pPathTmp->nextNode == NULL )
    } // if( pPath->pOneTreeCplLevel->cType == TYPE_EXPR )

    *(pPath->pOneTreeCplLevel->pKeyword + pPath->pOneTreeCplLevel->iKeywordLen) = cKeywordEnd;
    *(pThisPathHead->pTree->pName + pThisPathHead->pTree->iNameLen) = cTreeNameEnd;

    if( pPath->nextNode )
    {
        if( ! checkEndOfLine_Any(pThisPathHead, pPath->nextNode, iPathY) )
            return false;
    }

    if( pPath->next )
    {
        if( ! checkEndOfLine_Any(pThisPathHead, pPath->next, iPathY) )
            return false;
    }

    return true;
}

bool CZGLanguage::checkCplTreeInfLoop(char *pTreeName, unsigned int iTreeNameLen)
{
    struct stString *pTreeNameListTmp = pTreeNameList4Check;
    for( ; pTreeNameListTmp; pTreeNameListTmp=pTreeNameListTmp->next )
    {
        if( pTreeNameListTmp->iStrLen == iTreeNameLen
         && ! strncmp(pTreeNameListTmp->pStr, pTreeName, iTreeNameLen) )
        {

            unsigned int iLen = 0;

            pTreeNameListTmp = pTreeNameList4Check;
            for( ; pTreeNameListTmp; pTreeNameListTmp=pTreeNameListTmp->next )
            {
                iLen += pTreeNameListTmp->iStrLen + 4;
            }
            iLen += iTreeNameLen + 4 + 100;
// printf("Mem len : %d\n", iLen);  // debug

            char *pErrorInfo = (char *)malloc(iLen);
            memset(pErrorInfo, 0x00, iLen);
            char *pTmp = pErrorInfo;

            *(pTreeName + iTreeNameLen) = '\0';
            sprintf(pTmp, "Error : Exists infinite loop for tree name : [ %s->", pTreeName);
            for( ; *pTmp != '\0'; pTmp ++ );

// printStrForDebug("", pTreeName, iTreeNameLen);  // debug

            pTreeNameListTmp = pTreeNameList4Check;
            for( ; pTreeNameListTmp; pTreeNameListTmp=pTreeNameListTmp->next )
            {
                if( pTreeNameListTmp->iStrLen == iTreeNameLen
                 && ! strncmp(pTreeNameListTmp->pStr, pTreeName, iTreeNameLen) )
                {
// printStrForDebug("", pTreeNameListTmp->pStr, pTreeNameListTmp->iStrLen);  // debug

                    *(pTreeNameListTmp->pStr + pTreeNameListTmp->iStrLen) = '\0';
                    sprintf(pTmp, "%s ]\n", pTreeNameListTmp->pStr);
                    printf(pErrorInfo);
                    break ;
                }
// printStrForDebug("", pTreeNameListTmp->pStr, pTreeNameListTmp->iStrLen);  // debug

                *(pTreeNameListTmp->pStr + pTreeNameListTmp->iStrLen) = '\0';
                sprintf(pTmp, "%s->", pTreeNameListTmp->pStr);
                for( ; *pTmp != '\0'; pTmp ++ );
            }

            return false;
        }
    }

// printStrForDebug("    Tree", pTreeName, iTreeNameLen);  // debug

    pTreeNameListTmp = getStringNode();
    memset(pTreeNameListTmp, 0x00, sizeof(struct stString));
    pTreeNameListTmp->pStr = pTreeName;
    pTreeNameListTmp->iStrLen = iTreeNameLen;

    pTreeNameListTmp->next = pTreeNameList4Check;
    pTreeNameList4Check = pTreeNameListTmp;

    struct stPathHead * pPathHeadTmp = pstPathHeadList;
    for( ; pPathHeadTmp; pPathHeadTmp=pPathHeadTmp->next )
    {
        if( pPathHeadTmp->pTree->iNameLen != iTreeNameLen
         || strncmp(pPathHeadTmp->pTree->pName, pTreeName, iTreeNameLen) )
            continue ;

        struct stPath *pPathTmp = pPathHeadTmp->pPathList;
        for( ; pPathTmp; pPathTmp=pPathTmp->next )
        {
            // if( pPathTmp->pOneTreeCplLevel->cType != 'P' )
            if( pPathTmp->pOneTreeCplLevel->cType != TYPE_PATH )
                continue ;

            if( ! checkCplTreeInfLoop(pPathTmp->pOneTreeCplLevel->pKeyword, pPathTmp->pOneTreeCplLevel->iKeywordLen) )
                return false;

// printStrForDebug("        Tree", pTreeNameList4Check->pStr, pTreeNameList4Check->iStrLen);  // debug

            pTreeNameListTmp = pTreeNameList4Check;
            pTreeNameList4Check = pTreeNameList4Check->next;
            freeStringNode( & pTreeNameListTmp);
        }
    }

    return true;
}

bool CZGLanguage::checkCplTreePaths()
{
    // Check infinite loop

    pTreeNameList4Check = NULL;

    struct stTree *pOneTree = pstTreeList;
    for( ; pOneTree; pOneTree=pOneTree->next )
    {
// printStrForDebug("Check Tree", pOneTree->pName, pOneTree->iNameLen);  // debug

        if( ! checkCplTreeInfLoop(pOneTree->pName, pOneTree->iNameLen) )
            return false;

// printf("        pTreeNameList4Check->next = %p\n", pTreeNameList4Check->next);
// printStrForDebug("        Tree", pTreeNameList4Check->pStr, pTreeNameList4Check->iStrLen);  // debug

        freeStringNode( & pTreeNameList4Check);
        pTreeNameList4Check = NULL;
    }

    ///////////////////////////////////////////////////////

    // Check the end of line 

    struct stPathHead * pPathHeadTmp = pstPathHeadList;
    for( ; pPathHeadTmp; pPathHeadTmp=pPathHeadTmp->next )
    {
        if( ! checkEndOfLine_Any(pPathHeadTmp, pPathHeadTmp->pPathList, pPathHeadTmp->iPathY - 1) )
            return false;
    }

    return true;
}


