//[참고]{----------------------------------------------------------
//"SysUtils.hpp"
//에 파일관련 처리나 중요 유용한 수많은 함수가 들어있다.
//파일 확장자처리및 파일 이름 처리를 위한 좋은 함수들이 많이 있다.
//}----------------------------------------------------------------

//[2005.08.20.토][생성!!!]{-----------------------------------------
//database 를 구성하고 내부 정보에 접근 할수 있는 method 를 만든다.
//}-----------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "database.h"
#include "ide_library.h"
#include "library.h"
#include "parser.h"


//[2012.06.19.화][추가!!!]
#include "ide_main.h"


//==============================================================================
//[DATABASE]====================================================================
//==============================================================================


//[DATABASE]
//{
    //--------------------------------------------------------------
    //실제 사용할 {database} 를 생성한다.
    //1 개만 생성하면 된다. 모든 정보가 이 안에 통합 관리 되므로...
    class   DATABASE        _database;
    //--------------------------------------------------------------

    void __fastcall DATABASE_GetPtr(class DATABASE **pDATABASEptr)
    {
      //[2005.08.29.월][생성!!!]{------------------------------------------------
      //다른 [소스 파일] 에서 {DATABASE} 의 pointer 를 얻고자 할때 사용한다.
      //{DATABASE} 자체는 한개 뿐이므로 직접 여러 곳에 선언할수는 없다.
      //이 떄 이 함수를 사용하여 {DATABASE} 본체의 주소값을 얻을수 있다.

      //**pDATABASEptr : 실제 {DATABASE} 를 가리킬 포인터를 인수로 념겨 받으므로
      //                 2 중포인터가 된다.
      //}------------------------------------------------------------------------

      //전역 변수로 선언된 _database 의 주소값을 넘겨준다.
      (*pDATABASEptr) = &_database;
      
      return;

    }
    
//}

//[TEMPDATABASE]
//{
    //[2006.07.24.월][추가!!!]
    //{
        //{tempdatabase} 는 유일하게 한개만 있으면 되므로 [전역변수] 개념으로
        //한개만 선언한다.
        class TEMPDATABASE      _tempdatabase;

    //}

    void __fastcall TEMPDATABASE_GetPtr(class TEMPDATABASE **pTEMPDATABASEptr)
    {
      //[2005.08.29.월][생성!!!]{------------------------------------------------
      //다른 [소스 파일] 에서 {DATABASE} 의 pointer 를 얻고자 할때 사용한다.
      //{DATABASE} 자체는 한개 뿐이므로 직접 여러 곳에 선언할수는 없다.
      //이 떄 이 함수를 사용하여 {DATABASE} 본체의 주소값을 얻을수 있다.

      //**pDATABASEptr : 실제 {DATABASE} 를 가리킬 포인터를 인수로 념겨 받으므로
      //                 2 중포인터가 된다.
      //}------------------------------------------------------------------------

      //전역 변수로 선언된 _database 의 주소값을 넘겨준다.
      (*pTEMPDATABASEptr) = &_tempdatabase;
      
      return;

    }

//}

//[CTRLAREASTACK]
//{
    //[2008.10.27.월][추가!!!]{---------------------------------------------------------------
    //소스당 한개만 잇으면 되고 검증과 번역시 필요한 정보를 관리 하므로 전역 변수로 선언한다.
    //}---------------------------------------------------------------------------------------

    struct CTRLAREASTACK _ctrlAreaStack;

//}

//==============================================================================
//==============================================================================
//==============================================================================

//[생성자]/[소멸자] 함수를 만든다.
__fastcall DATABASE::DATABASE(void)
{
  //[2005.08.29.월][생성!!!]{--------------------------------
  //[생성자 함수] 로써 {DATABASE} 의 각종 초기화를 수행한다.
  //
  //[2012.04.20-1.목][추가!!!]-------------------------------
  //[STRHEAP] 는 반드시 처음 한번은 초기화 해준다.
  //
  //[2012.05.17.목][수정!!!]---------------------------------
  //}--------------------------------------------------------

  //[STRHEAP]
  //{
      //[2012.04.20-1.목][추가!!!]{-----
      //처음 한번만 반드시 초기화 한다.
      //}-------------------------------

      STRHEAP_Init(&_strHeap);

  //}

  //[ERRORINFO]
  //{
      //[2012.04.27.금][추가!!!]{--------------
      //반드시 한번만 여기서 처음 초기화 한다.
      //}--------------------------------------

      STRBUF_FirstInit(&(errorinfo.strbuf));

  //}

  //[FILEINFO]
  //{
      //[2012.04.27.금][추가!!!]{---
      //반드시 한번만 초기화 한다.
      //}---------------------------

      FILEINFO_FirstInit(&(fileinfo));

  //}

  //[STRINGLIST]
  //{
      //[2012.04.28.토][추가!!!]{---
      //반드시 한번만 초기화 한다.
      //}---------------------------

      STRINGLIST_FirstInit();

  //}

  //[TEMPFILE]
  //{
      //[2012.04.28.토][추가!!!]
      STRBUF_FirstInit(&tempfile);

  //}

  //[DATABASE]
  //{
      Init();

  //}

  //[공용 문자열 정보]
  //{
      //[2012.05.17.목][추가!!!]{---------------------------------------
      //[형식 적용 문자열(편집기:색동문자 유사기능)] 출력 등에 사용되는
      //[비교 문자열] 을 관리하는 [범용] [STRHEAP].
      //
      //여기서 한번 [초기화/생성] 하면 된다.
      //
      //[삭제] 는 <~DATABASE()> 에서 한번만 한다.
      //계속 유지돼야 하는 정보다.
      //
      //[주의!!!]-------------------------------------------------------
      //<Init()> 에서 초기화 되는 <keywordlist[]> 등 [예약어] 관련 중요
      //[단어] 정보를 사용하므로 반드시 <Init()> 다음에 처리해야 한다.
      //}---------------------------------------------------------------

      STRHEAP_Init(&_strHeap_Conf);

      //여기서 한번만 [생성] 한다.
      //기본 10K 정도면 충분(내부적으로 자동 증가된다).
      STRHEAP_Create(&_strHeap_Conf, 10*1024, 1024);

      //기본 초기화.
      StrHeapConf_Init();

  //}

}

__fastcall DATABASE::~DATABASE(void)
{
  //[2005.08.29.월][생성!!!]{---------------------------------------
  //[소멸자 함수] 로써 {DATABASE} 삭제될 때의 기본 처리를 수행한다.
  //
  //[2012.05.17.목][수정!!!]----------------------------------------
  //}---------------------------------------------------------------

  //[공용 문자열 정보]
  //{
      //[2012.05.17.목][추가!!!]{---
      //유일하게 여기서 한번 삭제.
      //}---------------------------

      STRHEAP_Delete(&_strHeap_Conf);

  //}

  //동적 생성된 내용들이 있다면 모두 해제해 준다.
  Delete();

}

//------------------------------------------------------------------------------

void __fastcall DATABASE::Init(void)
{
  //[2005.08.20.토][생성!!!]{----------------------
  //database 의 record 와 모든 정보를 초기화 한다.
  //
  //[2012.04.07.토][수정!!!]-----------------------
  //[2012.04.20-1.목][수정!!!]---------------------
  //[2012.04.22.일][설명!!!]-----------------------
  //}----------------------------------------------


  //[VAR]
  //{
      int  i, j;

  //}

  //[STRHEAP]
  //{
      //[2012.04.20-1.목][추가!!!]{----------------------------------
      //이미 생성된 것이 있을수 있으므로 [삭제] 후 기본생성한다.
      //
      //[2012.04.22.일][설명!!!]-------------------------------------
      //아래의 <REC_Init()> 안에서는 <str_mem:-1> 로만 초기화 하므로
      //반드시 이곳에서 먼저 [삭제] 처리를 해야 한다.
      //순서가 바뀌면 절대 안된다!!!
      //}------------------------------------------------------------

      //반드시 기존 생성된것을 삭제.
      STRHEAP_Delete(&_strHeap);

      //기본크기로 새로 생성.
      STRHEAP_Create(&_strHeap, d_STRHEAP_Heap_addSize, d_STRHEAP_List_addSize);

  //}

  //[2005.08.29.원][추가!!!]{-----------------------------
  //record 수는 기본적으로 0 (비어있음) 으로 초기화 한다.
  record_count = 0;
  //}-----------------------------------------------------

  //[항목 초기화]
  //{
      //[2005.09.07.수][수정!!!]{---------------------------------------------
      //개별적인 초기화 보다는 REC_Format() 함수를 사용하여 [record] 단위로
      //초기화 하는 것이 간단하다.
      //
      //[2012.04.22.일][참고!!!]----------------------------------------------
      //이미 위에서 [STRHEAP] 를 [동적삭제] 하였으므로 여기서 <str_mem:-1> 로
      //바로 초기화 해도 무방하다.
      //}---------------------------------------------------------------------

      for(i=0; i<OPT_record_size; i++)
      {
        REC_Init(&(record[i]));

      }

  //}

  //[2005.09.07.수][추가!!!]{---
  REC_Init(&temprecord);
  //}---------------------------


  //[ERRORINFO][2006.04.15.금][추가!!!]
  //{
      ERRORINFO_Init();

  //}


  //[2005.11.05.토][주의!!!][추가!!!]{------------------------------------------------
  //가장 처음 IS_Name() 으로 검사하는 경우 {DATABASE} 에 아무 것도 없는 경우는
  //record_count = 0 으로 검색 자체가 되지 않아 error 가 발생하게 되므로
  //이를 막기 위하여 dummy-record 를 하나 추가한다.
  //완전 format 된 것을 하나 추가해 주면 된다. 이미 format 된 temprecord 를 추가한다.
  REC_Add(&temprecord, &i);
  //}---------------------------------------------------------------------------------


  //------------------
  //추가 정보 초기화.
  //------------------

  //[주소관련 정보 초기화]
  //{
      //[2008.11.06.목][추가!!!]{----------------------------
      //@DATA 를 기준으로한 [추가주소] 값은 0 부터 시작한다.
      //}----------------------------------------------------

      _DATA_ofsADR = 0;

  //}

  //[parserinfo 관련 초기화]
  //{
      //parserinfo 는 실제 {DATABASE} 상에 한개만 사용되므로 1 개만 초기화 한다.
      PARSERINFO_Format(&parserinfo);

      //parserinfostack[] 은 #include 문을 만나서 [새로운 파일] 을 열어야 할 필요가
      //있는 경우 현재 작업중인 [파일] 의 어디 까지를 처리 했는지 등의 정보가 들어
      //있는 parserinfo 를 Push, Pop 하는 공간이 된다.(매우 중요)
      parserinfostack_count = 0;
      for(i=0; i<OPT_parserinfostack_size; i++)
      {
        PARSERINFO_Format(&(parserinfostack[i]));

      }

  //}

  //[fileinfo 초기화]{------------------------------------------------------------
  //{DATABASE} 안에 "오직 1 개" 만 있으므로 한개만 초기화 한다.
  //compile 대상이 되는 file 을 열떄는 반드시 이 정보를 사용해야 한다.
  //전역 변수처럼 사용한다.
  FILEINFO_Format(&fileinfo);

  //항상 첫 파일 이름은 가상정보로 "GIGYEIN" 으로 해야 한다.
  //"GIGYEIN" 파일은 실제 존재하지 않는 것으로 모든 file 의 시작과 끝을 의미한다.
  //즉, [파일이름] 이 "GIGYEIN" 이라면 더이상 처리할 파일이 없는 것이므로
  //parser 를 종료하면 된다.
  STR_Assign(fileinfo.name, "GIGYEIN");
  fileinfo.size = STR_Length(fileinfo.name) + 1;
  //}-----------------------------------------------------------------------------

  //[filelist 초기화]{---------------------------------------------------
  filelist_count = 0;
  for(i=0; i<OPT_file_name_list_size; i++)
  {
    filelist[i].name[0] = '\0';
    filelist[i].size    = 0;

    //[2005.10.12.수][추가!!!]{-------------------------
    //새로 추가된 include file 관리 배열을 초기화 한다.
    //처음에는 아무 것도 없다는 의미도 -1 을 할당한다.
    for(j = 0; j < OPT_include_list_size; j++)
    {
      filelist[i].include_list[j]  = -1;

    }

    filelist[i].include_list_count = 0;
    //}-------------------------------------------------

    //[<includeListTotal> 관련]
    //{
        //[2012.04.07.토][추가!!!]
        for(j = 0; j < OPT_IncludeListTotal_size; j++)
        {
          filelist[i].includeListTotal[j]  = -1;

        }

        filelist[i].includeListTotalCount = 0;

    //}

  }

  //[2005.09.12.월][추가!!!]
  //이미 초기화된 fileinfo 정보를 하나 추가해 준다.
  //"파일 정보의 시작과 끝을 알려 주기 위하여 값을 하나 채워 놓아야 한다."
  //가장 처음에는 무조건 "GIGYEIN" 이 filename 으로 할당된다.
  FILELIST_Add(fileinfo.name, fileinfo.size);
  //}--------------------------------------------------------------------

  //[typelist 초기화]
  //{
      typelist_count = 0;

      for(i=0; i<OPT_type_list_size; i++)
      {
        typelist[i].type[0]   = '\0';

        //처음에는 아무것도 참조하지 않는 것이다.
        typelist[i].rec_index = -1;

        //[2007.07.20.금][추가!!!]
        //기본적으로 크기는 0 으로 초기화 한다.
        typelist[i].size = 0;

      }

  //}

  //[defilelist 초기화][2005.10.15.토][추가!!!]{---
  definelist_count = 0;

  for(i=0; i<OPT_define_list_size; i++)
  {
    DEFINELIST_Format(&(definelist[i]));

  }

  //[2006.05.09.화][추가!!!]
  definecall_count = 0;
  //}----------------------------------------------

  //[uselabellist 초기화][2006.02.15.수][추가!!!]{---
  uselabellist_count = 0;
  for(i=0; i<OPT_uselabel_list_size; i++)
  {
    uselabellist[i].name[0]       = '\0';
    uselabellist[i].filelistindex = -1;
    uselabellist[i].area          = -1;

  }
  //}------------------------------------------------


  //[stringlist 초기화][2006.06.02.금][추가!!!]
  //{
      STRINGLIST_Init();
  //}


  //[2005.08.27.토][추가!!!]{-----
  //부가정보 초기화를 수행한다.
  //}-----------------------------


  //[keyword 초기화]
  //{
      i = 0;
      STR_Assign(keywordlist[i++].kw, "break");
      STR_Assign(keywordlist[i++].kw, "else");
      STR_Assign(keywordlist[i++].kw, "switch");
      STR_Assign(keywordlist[i++].kw, "case");
      STR_Assign(keywordlist[i++].kw, "return");
      STR_Assign(keywordlist[i++].kw, "continue");
      STR_Assign(keywordlist[i++].kw, "for");
      STR_Assign(keywordlist[i++].kw, "default");
      STR_Assign(keywordlist[i++].kw, "goto");
      STR_Assign(keywordlist[i++].kw, "do");
      STR_Assign(keywordlist[i++].kw, "if");
      STR_Assign(keywordlist[i++].kw, "while");

      STR_Assign(keywordlist[i++].kw, "struct");
      STR_Assign(keywordlist[i++].kw, "union");
      STR_Assign(keywordlist[i++].kw, "double");
      STR_Assign(keywordlist[i++].kw, "int");
      STR_Assign(keywordlist[i++].kw, "long");
      STR_Assign(keywordlist[i++].kw, "char");
      STR_Assign(keywordlist[i++].kw, "float");
      STR_Assign(keywordlist[i++].kw, "short");
      STR_Assign(keywordlist[i++].kw, "unsigned");
      STR_Assign(keywordlist[i++].kw, "signed");
      STR_Assign(keywordlist[i++].kw, "void");

      STR_Assign(keywordlist[i++].kw, "include");
      STR_Assign(keywordlist[i++].kw, "define");
      STR_Assign(keywordlist[i++].kw, "undef");

  //}

  //[연산자 초기화]
  //{
      i = 0;
      STR_Assign(operatorlist[i++].op, "-");
      STR_Assign(operatorlist[i++].op, "->");
      STR_Assign(operatorlist[i++].op, "--");
      STR_Assign(operatorlist[i++].op, "-=");
      STR_Assign(operatorlist[i++].op, "+");
      STR_Assign(operatorlist[i++].op, "++");
      STR_Assign(operatorlist[i++].op, "+=");
      STR_Assign(operatorlist[i++].op, "<");
      STR_Assign(operatorlist[i++].op, "<<");
      STR_Assign(operatorlist[i++].op, "<<=");
      STR_Assign(operatorlist[i++].op, "<=");
      STR_Assign(operatorlist[i++].op, ">");
      STR_Assign(operatorlist[i++].op, ">>");
      STR_Assign(operatorlist[i++].op, ">>=");
      STR_Assign(operatorlist[i++].op, ">=");
      STR_Assign(operatorlist[i++].op, "=");
      STR_Assign(operatorlist[i++].op, "==");
      STR_Assign(operatorlist[i++].op, "!");
      STR_Assign(operatorlist[i++].op, "!=");
      STR_Assign(operatorlist[i++].op, "&");
      STR_Assign(operatorlist[i++].op, "&&");
      STR_Assign(operatorlist[i++].op, "&=");
      STR_Assign(operatorlist[i++].op, "|");
      STR_Assign(operatorlist[i++].op, "||");
      STR_Assign(operatorlist[i++].op, "|=");
      STR_Assign(operatorlist[i++].op, "^");
      STR_Assign(operatorlist[i++].op, "^=");
      STR_Assign(operatorlist[i++].op, "*");
      STR_Assign(operatorlist[i++].op, "*=");
      STR_Assign(operatorlist[i++].op, "/");
      STR_Assign(operatorlist[i++].op, "/=");
      STR_Assign(operatorlist[i++].op, "%");
      STR_Assign(operatorlist[i++].op, "%=");
      STR_Assign(operatorlist[i++].op, ".");
      STR_Assign(operatorlist[i++].op, "~");
      STR_Assign(operatorlist[i++].op, "?");
  //}

  //[기호 초기화]
  //{
      i = 0;
      STR_Assign(signlist[i++].sign, "*/");
      STR_Assign(signlist[i++].sign, "/*");
      STR_Assign(signlist[i++].sign, "#");
      STR_Assign(signlist[i++].sign, "[");
      STR_Assign(signlist[i++].sign, "]");
      STR_Assign(signlist[i++].sign, "(");
      STR_Assign(signlist[i++].sign, ")");
      STR_Assign(signlist[i++].sign, ",");
      STR_Assign(signlist[i++].sign, "\"");
      STR_Assign(signlist[i++].sign, "\'");
      STR_Assign(signlist[i++].sign, ";");
      STR_Assign(signlist[i++].sign, ":");
      STR_Assign(signlist[i++].sign, "\\");
      STR_Assign(signlist[i++].sign, "{");
      STR_Assign(signlist[i++].sign, "}");
  //}

  //[escape 초기화]
  //{
      //escape 문자는 '\t' 등 보다 많은 것이 있으므로 향후 지원할 것은
      //이곳에 추가한다.
      i = 0;
      STR_Assign(escapelist[i++].escape, "\\\\");  //[\\]
      STR_Assign(escapelist[i++].escape, "\\n");   //[\n]
      STR_Assign(escapelist[i++].escape, "\\0");   //[\0]
      STR_Assign(escapelist[i++].escape, "\\\"");  //[\"]
      STR_Assign(escapelist[i++].escape, "\\\'");  //[\']
      STR_Assign(escapelist[i++].escape, "\\r");   //[\r]
      STR_Assign(escapelist[i++].escape, "\\t");   //[\t]
  //}


  //[기타 초기화]
  //{


      // ...


  //}


  //[2005.09.05.월][추가!!!]{------------------------------
  //사전에 가지고 있어야할 문자열이 있는 경우 초기화 한다.
  FILL_Type();

  //필요한 경우 추가...
  //}------------------------------------------------------


  //[영역스택 초기화]
  //{
      //[2008.10.27.월][추가!!!]
      CTRLAREASTACK_Init();

  //}

  return;

}

void __fastcall DATABASE::FILL_Type(void)
{
  //[2005.09.05.월][생성!!!]{------------------------------------------
  //{DATABASE} 와 typelst[] 에 C-언어 의 기본 [type] 을 초기화 해준다.
  //}------------------------------------------------------------------

  //[2005.11.1.화][수정!!!]
  //{
      //"unsigned char", "signed int" 등도 전부 한개의 type 으로 간주하여 처리한다.
      //이렇게 하는 이유는, type 을 반환해야 하는 인수가 한개이므로 한개로 합쳐야
      //하기 때문이다. C 언어의 기본 type 이 많지 않으므로 완전히 별개의 것으로
      //구분해서 저장한다.
  //}

  //[2007.07.20.금][수정!!!]
  //{
      //typelist[].size 정보까지 처리하는 것으로 수정하였다.
  //}

  //[주의!!!]
  //{
      //저장 순서가 바뀌지 않도록 주의한다.
  //}


  //[VAR]
  //{
      int   typelistindex = 0;
  //}


  //[typelist[] 초기화]
  //{
      //이 정보는 가장 처음에 저장되어야 하므로,
      //typelistcount = 0; 으로 되 있어야 한다.
      //이 것은 기본 type 이므로 record-index 는 -1 로 넣으면 된다.
      //다른 함수에서 처리시 비교하기 쉽도록 순서대로 저장하고 비교시 index 로
      //범위를 지정하여 간단하게 검색할수 있도록 한다.
      //           [TYPE]                                [INDEX]
      TYPELIST_Add("void",     -1, &typelistindex);        //0
      //포인터이므로 64bit 크기를 갖는 것으로 정의한다.
      TYPELIST_Set_Size(typelistindex, 8);

      TYPELIST_Add("signed",   -1, &typelistindex);        //1
      //기본적으로 signed int 가 된다.
      TYPELIST_Set_Size(typelistindex, 4);

      TYPELIST_Add("unsigned", -1, &typelistindex);        //2
      //기본적으로 unsigned int 가 된다.
      TYPELIST_Set_Size(typelistindex, 4);

      //signed type 군.
      TYPELIST_Add("signed char",  -1, &typelistindex);    //3
      TYPELIST_Set_Size(typelistindex, 1);

      TYPELIST_Add("signed short", -1, &typelistindex);    //4
      TYPELIST_Set_Size(typelistindex, 2);

      TYPELIST_Add("signed int",   -1, &typelistindex);    //5
      TYPELIST_Set_Size(typelistindex, 4);

      TYPELIST_Add("signed long",  -1, &typelistindex);    //6
      TYPELIST_Set_Size(typelistindex, 8);

      //unssigned type 군.
      TYPELIST_Add("unsigned char",  -1, &typelistindex);  //7
      TYPELIST_Set_Size(typelistindex, 1);

      TYPELIST_Add("unsigned short", -1, &typelistindex);  //8
      TYPELIST_Set_Size(typelistindex, 2);

      TYPELIST_Add("unsigned int",   -1, &typelistindex);  //9
      TYPELIST_Set_Size(typelistindex, 4);

      TYPELIST_Add("unsigned long",  -1, &typelistindex);  //10
      TYPELIST_Set_Size(typelistindex, 8);

      //기본 type 군.
      TYPELIST_Add("char",   -1, &typelistindex);          //11
      TYPELIST_Set_Size(typelistindex, 1);

      TYPELIST_Add("short",  -1, &typelistindex);          //12
      TYPELIST_Set_Size(typelistindex, 2);

      TYPELIST_Add("int",    -1, &typelistindex);          //13
      TYPELIST_Set_Size(typelistindex, 4);

      TYPELIST_Add("long",   -1, &typelistindex);          //14
      TYPELIST_Set_Size(typelistindex, 8);

      //내가만든 C 에서는 float 나 double 나 모두 8byte 다.
      TYPELIST_Add("float",  -1, &typelistindex);          //15
      TYPELIST_Set_Size(typelistindex, 8);

      TYPELIST_Add("double", -1, &typelistindex);          //16
      TYPELIST_Set_Size(typelistindex, 8);

  //}

  //[2005.10.31.월][수정!!!]{----------------------------------------------------
  //이전과 달리 기본 type 은 {DATABASE} 에 저장할 필요가 없다.
  //이것들은 전부 keywordlist[] 에 있고, 이 keywordlist[] 의 내용이 name 판별시
  //사용되므로...
  //}----------------------------------------------------------------------------

  return;

}

void __fastcall DATABASE::Delete(void)
{
  //[2005.09.07.수][생성!!!]{---------------------------------------
  //{DATABASE} 의 정보중 동적으로 생성된 정보가 NULL 이 아닌 경우는
  //동적으로 삭제해 주어야 한다. 사용한 부분까지만 처리한다.
  //
  //[2012.04.20-1.목][수정!!!]--------------------------------------
  //}---------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  //[STRHEAP]
  //{
      //[2012.04.20-1.목][추가!!!]{--------
      //사용한 [STRHEAP] 을 완전 삭제한다.
      //}----------------------------------

      STRHEAP_Delete(&_strHeap);

  //}


  for(i=0; i<record_count; i++)
  {
    if(record[i].arraysize != NULL)
    {
      //먼저 동적 생성된 메모리를 해제해준다.
      delete [] record[i].arraysize;

    }

    record[i].arraysize = NULL;

  }

  //[2012.04.20-1.목][주석처리!!!]
  //[STRHEAP] 방식으로 변경.
  //<str_mem> 은 [동적삭제] 대상이 아니다.
  /*
  for(i=0; i<record_count; i++)
  {

    if(record[i].str_mem != NULL)
    {
      //먼저 동적 생성된 메모리를 해제해준다.
      delete [] record[i].str_mem;

    }

    record[i].str_mem = NULL;

  }
  */

  //[2005.09.08.목][추가!!!]{---------
  //임시 record 의 내용도 삭제해준다.
  if(temprecord.arraysize != NULL)
  {
    delete [] temprecord.arraysize;

  }

  temprecord.arraysize = NULL;
  //}---------------------------------

  //[삭제]
  //{
      //[2012.04.27.금][추가!!!]{-----------------------------------
      //기존에 생성된 것이 있다면 [삭제] 한다.
      //{DB} 시작시 한번 <STRBUF_FirstInit()> 로 초기화 했기 때문에
      //처음에는 항상 NULL 로 시작하므로 안전하게 사용할수 있다.
      //}-----------------------------------------------------------

      STRBUF_Delete(&(errorinfo.strbuf));

      FILEINFO_Delete(&(fileinfo));

      //[2012.04.28.토][추가!!!]
      STRINGLIST_Delete();

      //[2012.04.28.토][추가!!!]
      TEMPFILE_Delete();

  //}

}

//[record 관련 함수]{-----------------------------------------------------------

void __fastcall DATABASE::REC_Get_RecordCount(int *pRECcount)
{
  //[2005.10.25.화][생성!!!]{------------------------------------------------
  //{DATABASE} 의 record_count 값을 반환한다.
  //{DATABASE} 의 중요한 모든 정보는 private: 로 보호되 있으므로 외부에서 이
  //값을 알고자 하는 경우 이 함수를 사용하면 된다.
  //}------------------------------------------------------------------------

  (*pRECcount) = record_count;

  return;

}

void __fastcall DATABASE::REC_Init(struct RECORD *pRECORD)
{
  //[2005.09.07.수][생성!!!]{-----------------------------------------------------
  //전달받은 record 의 각각 field 에 초기 값을 기록한다.
  //
  //[2005.10.28.금][주의!!!]{-----------------------------------------------------
  //만일 record 를 LOCAL 에서 처음 생성한 뒤 이 함수로 바로 초기화 하면
  //pointer 와 관련된 system error 가 발생할수 있는데, local 의 경우
  //pRECORD->arraysize 포인터가 NULL 로 초기화 되 있지 않아서 어떤 값을 가지게
  //되고(임의 값), delete [] pRECORD->arraysize; 로 delete 를 시도할때
  //임의 포인터 값이므로 사실 해제할 memory 가 아닌것이 되어 당연히 error 가
  //날수밖에는 없게 된다. 없는 것을 delete 하게 되는 것이므로...
  //이에 이 함수 사용시는 각별히 주의를 해야 한다.
  //단순하게 local 에서 record 를 선언뒤 초기화 하는 것은
  //REC_Format() 함수를 사용하여 처리한다.
  //
  //[2012.04.20-1.목][수정!!!]----------------------------------------------------
  //[2012.04.22.일][설명!!!]------------------------------------------------------
  //일단, <str_mem> 에 등록된 문자열이 있는 경우를 무시하고 <-1> 로 초기화 한다.
  //실제 <DATABASE::Init()> 에서만 사용되고 있고, 항상 먼저 참조 대상인
  //[STRHEAP] 이 [삭제] 되고 사용되므로 <-1> 로 그냥 초기화 해도 무관하다.
  //
  //더불어 현재 {DB} 는 [STRHEAP] 에 [재할당] 조차 없는 [추가] 만 존재하기 때문에
  //그대로 <-1> 로 초기화해도 된다.
  //}-----------------------------------------------------------------------------

  //처음에는 아무 문자 열도 없는 것이다.
  pRECORD->name[0]       = '\0';
  pRECORD->index         = -1;
  pRECORD->kind          = -1;
  pRECORD->area          = -1;
  pRECORD->typelistindex = -1;
  pRECORD->filelistindex = -1;
  pRECORD->pointer       = 0;
  pRECORD->motherindex   = -1;

  //[배열]{---------------------------------------------------------
  pRECORD->arraydimension = 0;

  //"arraysize" 정보는 동적으로 생성되므로 NULL 이 아닐 경우는 먼저
  //내용을 동적으로 삭제해 주어야 한다.

  if(pRECORD->arraysize != NULL)
  {
    //먼저 동적 생성된 메모리를 해제해준다.
    delete [] pRECORD->arraysize;

  }

  pRECORD->arraysize = NULL;
  //}---------------------------------------------------------------

  //[2006.01.26.목][추가!!!]{-----------------------------------
  //동적으로 생성된 정보는 완전히 삭제하고 초기화 한다.
  //
  //[2012.04.20-1.목][주석처리!!!]------------------------------
  /*if(pRECORD->str_mem != NULL)
  {
    delete [] pRECORD->str_mem;

  }

  pRECORD->str_mem = NULL;
  */
  //[2012.04.20-1.목][수정!!!]----------------------------------
  //[STRHEAP] 방식으로 처리.
  //[2012.04.22.일][참고!!!]------------------------------------
  //일단, 여기서는 기존 참조대상을 [삭제] 하는 동작은 하지 않고
  //항상 <-1> 기본 값으로 초기화 하는것으로 한다.
  pRECORD->str_mem = -1;
  //}-----------------------------------------------------------

  //[2008.11.06.목][추가!!!]
  //{
      pRECORD->size    = 0;
      pRECORD->address = 0;

  //}

}

void __fastcall DATABASE::REC_Format(struct RECORD *pRECORD)
{
  //[2005.10.28.금][생성!!!]{------------------------------------------------
  //전달받은 record 의 각각 field 를 format 한다.
  //이 함수는 record 를 하나 선언한 다음에 반드시 해서 기본 값을 깔아 주어야
  //한다.  REC_Init() 와 다른 것은 막 생성된 상태라서 포인터가 어떤 memory
  //할당받은 것이 아니므로 굳이 delete 하지 않고 그냥 NULL 로 초기화 한다는
  //것이다.
  //
  //[2012.04.20-1.목][수정!!!]-----------------------------------------------
  //}------------------------------------------------------------------------

  //[기본초기화]
  //{
      //처음에는 아무 문자 열도 없는 것이다.
      pRECORD->name[0]       = '\0';
      pRECORD->index         = -1;
      pRECORD->kind          = -1;
      pRECORD->area          = -1;
      pRECORD->typelistindex = -1;
      pRECORD->filelistindex = -1;
      pRECORD->pointer       = 0;
      pRECORD->motherindex   = -1;

  //}

  //[배열]
  //{
      pRECORD->arraydimension = 0;

      //"arraysize" 정보는 동적으로 생성되나, 이 함수는 record 가 선언된 후
      //바로 사용되므로 아무 것도 생성된 것은 없다. 그러므로 그냥 NULL
      //로 바로 초기화 한다.
      pRECORD->arraysize = NULL;
  //}

  //[2006.01.26.목][추가!!!]
  //{
      //[2012.04.20-1.목][주석처리!!!]
      //pRECORD->str_mem = NULL;
      //[STRHEAP] 방식으로 변경.
      pRECORD->str_mem = -1;

  //}

  //[2008.11.06.목][추가!!!]
  //{
      pRECORD->size    = 0;
      pRECORD->address = 0;

  //}

}

bool __fastcall DATABASE::REC_Write(int            pRECindex,
                                    struct RECORD *pRECORD)
{
  //[2005.10.27.목][생성!!!]{-------------------
  //지정 위치에 전달받은 record 를 기록한다.
  //이미 내용이 있는 경우는 그냥 덮어쓰면 된다.
  //}-------------------------------------------

  //[반환값!!!]{----------------
  // true  : 이상없이 처리됬음.
  // false : error!
  //}---------------------------

  //[검사]
  //{
      //지정 index 범위 체크.
      if(!((0 <= pRECindex) && (pRECindex < record_count)))
      { //범위를 넘었으므로 error!
        return(false);

      }
  //}

  //[기록]
  //{
      //{DATABASE} 에 record 를 기록한다.
      record[pRECindex] = *pRECORD;
  //}

  //여기까지 온것은 아무 이상없는 것이다.
  return(true);

}

bool __fastcall DATABASE::REC_Field_Write(struct RECORD *pRECORD,
                                          int            pFIELDindex1,
                                          int            pFIELDindex2,
                                          void          *pDATA)
{
  //[2005.08.31.수][생성!!!]{------------------------------------------------------
  //{DATABASE} 의 지정된 [record] 의 지정된 [field] 에 [data] 를 기록한다.
  //각각의 [field] 는 전부 type 이 다룰수 있으므로 일단은 (void *) 로 인수를
  //전달 받고 해당 [field] 에 따라 (typecast) 하여 값을 읽어서 사용한다.

  //pFIELDindex1 : 실제 field 를 선택할때 사용되는 index 값.
  //pFIELDindex2 : 부가 정보(arraysize[]...) 에 접근하기 위하여 사용하는 index 값.
  //
  //[2012.04.20-1.목][수정!!!]-----------------------------------------------------
  //}------------------------------------------------------------------------------


  //[VAR]
  //{
      int  strlength;

  //}


  //[코드완성필요!!!]{--------------------------------------------------------
  //[type] 을 저장하게 되면 typelist[] 에도 같이 정보를 저장해 주어야 하는데,
  //이런 관련된 처리도 합께 수해해야할 필요가 있다.
  //추후 끼워 넣는다.
  //}-------------------------------------------------------------------------
  

  switch(pFIELDindex1)
  {
    case  _F_name :
          {
            //문자열을 직접 copy 해서 저장해야 한다.
            STR_Assign(pRECORD->name, ((char *)pDATA));
            return(true);

          } break;

    case  _F_index :
          {
            pRECORD->index = *((int *)pDATA);
            return(true);

          } break;

    case  _F_kind :
          {
            pRECORD->kind = *((int *)pDATA);
            return(true);

          } break;

    case  _F_area :
          {
            pRECORD->area = *((int *)pDATA);
            return(true);

          } break;

    case  _F_typelistindex :
          {
            pRECORD->typelistindex = *((int *)pDATA);
            return(true);

          } break;

    case  _F_filelistindex :
          {
            pRECORD->filelistindex = *((int *)pDATA);
            return(true);

          } break;

    case  _F_pointer :
          {
            pRECORD->pointer = *((int *)pDATA);
            return(true);

          } break;

    case  _F_motherindex :
          {
            pRECORD->motherindex = *((int *)pDATA);
            return(true);

          } break;

    case  _F_arraydimension :
          {
            pRECORD->arraydimension = *((int *)pDATA);

            //[2005.11.07.월][수정!!!][중요!!!]{----------------
            //array 는 5 차원 이상 선언할수 없도록 제한을 둔다.
            if(pRECORD->arraydimension > OPT_array_dimension)
            {
              //제한을 넘은 것이므로 error!!!
              return(false);

            }
            //}-------------------------------------------------

            //[!]{--------------------------------------------------------
            //[arraydimension] 이 결정 되었으므로 각각의 size 를 기록할
            //저장소를 만들어 준다. 이는 배열의 형식으로 접근하게 된다.
            //int ARY[A][B][C]; 의 경우 A, B, C 값을 저장할 공간을 만들어
            //주는 것이다.
            //}-----------------------------------------------------------

            //[이전 것 삭제]
            //{
                //먼저 NULL 이 아니라면 동적으로 생성된 것을 삭제한다.
                if(pRECORD->arraysize != NULL)
                {
                  delete [] pRECORD->arraysize; pRECORD->arraysize = NULL;

                }
            //}

            //[공간 생성]
            //{
                //[arraydimension] 에 맞는 공간을 생성한다.
                //pRECORD->arraysize = new int[pRECORD->arraydimension];
                //[동적생성단위적용][2021.01.24.일][수정]
                pRECORD->arraysize = new int[UnitX(1024, pRECORD->arraydimension)];

            //}

            return(true);

          } break;

    case  _F_arraysize :
          {
            //(arraysize != NULL) 일 경우 arraysize[pFILEindex2] 로 사용한다.
            //arraysize[] 는 동적으로 생성되는 정보이므로 사전에 크기를 정의
            //할수 없기 떄문이다. 사전에 이미 저장 공간이 만들어져 있어야 한다.

            //[2005.11.07.월][추가!!!][중요!!!]{--------------
            //arraydimension 의 범위를 넘어서 지정할수 없다.
            //실제로 index 이므로 0 ~ 4 까지만 된다.
            if(pRECORD->arraydimension <= pFIELDindex2)
            {
              //차원의 범위를 넘어서 지정한 것이므로 error!!!
              return(false);

            }
            //}-----------------------------------------------

            //[저장 공간 확인]
            //{
                //저장 공간이 만들어져 있는지 확인한다.
                if(pRECORD->arraysize == NULL)
                {
                  //아직 저장 공간이 없는 것이므로 저장 할수 없다!
                  //아무 처리도 하지 않고 바로 종료한다.
                  return(false);

                }
            //}

            //지정값을 저장한다.
            pRECORD->arraysize[pFIELDindex2] = *((int *)pDATA);

            return(true);

          } break;

    case  _F_str :
          {
            //[2006.01.26.목][추가!!!]{--------------------------------------------------
            //할당 하기 전에 먼저 할당맏을 문자열을 담을 크기만큼 memory 를
            //동적으로 할당해 주어야 한다. 그다음 전달받은 문자열을 할당한다.
            //완전히 copy 해 주어야 한다.
            //
            //[2012.04.22.일][중요수정!!!]-----------------------------------------------
            //[재할당/기존것삭제/자동추가] 기능을 모두 가진 <STRHEAP_Str()> 함수를 사용.
            //이미 <txt> 에 할당된 문자열이 있는 경우는 자동 [삭제] 후 [추가] 된다.
            //
            //실제 {DB} 에서는 [재할당] 의 경우가 없으므로 사실상 <STRHEAP_Str_Add()> 를
            //사용한 것과 결과는 동일하다.
            //}--------------------------------------------------------------------------

            //[2012.04.22.일][추가!!!]
            //이미 할당돼 있는 경우도 내부적으로 자동 삭제되고 추가된다.
            STRHEAP_Str(&_strHeap, &(pRECORD->str_mem), (char *)pDATA);

            //[2012.04.22.일][주석처리!!!]
            /*
            //[STRHEAP] 방식으로 변경.
            //[문자열] 을 전달하고 [목록번호(index)] 를 받는다.
            pRECORD->str_mem = STRHEAP_Str_Add(&_strHeap, (char *)pDATA);
            */

            return(true);

          } break;

    case  _F_size :
    {
      //[2008.11.05.수][추가!!!]

      pRECORD->size = *((long long *)pDATA);
      return(true);


    } break;

    case  _F_address :
    {
      //[2008.11.05.수][추가!!!]

      pRECORD->address = *((unsigned long long *)pDATA);
      return(true);

    } break;

  }

  //여기까지 온것은 해당하지 않는 것이므로 error!
  return(false);

}

bool __fastcall DATABASE::REC_Field_Write2(int   pRECORDindex,
                                           int   pFIELDindex1,
                                           int   pFIELDindex2,
                                           void *pDATA)
{
  //[2005.10.21.금][생성!!!]{--------------------------------------------------
  //REC_Field_Write 는 record 를 대상으로 하나, 이 함수는 record[] 의 index 로
  //직접 record[index] 로 작업 할수 있다.
  //}--------------------------------------------------------------------------

  return(REC_Field_Write(&(record[pRECORDindex]), pFIELDindex1, pFIELDindex2, pDATA));

}

bool __fastcall DATABASE::REC_Field_Read(struct RECORD *pRECORD,
                                         int            pFIELDindex1,
                                         int            pFIELDindex2,
                                         void          *pDATA)
{
  //[2005.08.31.수][생성!!!]{------------------------------------
  //{DATABASE} 에서 지정된 [record] 의 [filed] 에서 [field] 값을
  //읽어서 반환한다.
  //[field] 값은 여러 [type]  으로 되 있으므로 (void *) 형으로
  //값을 넘겨준다.
  //}------------------------------------------------------------


  //[VAR]
  //{
  //}


  //[코드완성필요!!!]{--------------------------------------------------------
  //[type] 을 저장하게 되면 typelist[] 에도 같이 정보를 저장해 주어야 하는데,
  //이런 관련된 처리도 합께 수해해야할 필요가 있다.
  //추후 끼워 넣는다.
  //}-------------------------------------------------------------------------


  switch(pFIELDindex1)
  {
    case  _F_name :
          {
            //주는 쪽에서는 [문자열 포인터] 만 넘겨주면 되고, 이 함수를 call
            //한 쪽에서 문자열을 copy 해서 저장해야 한다. (알아서 처리)

            //[사용법]{-----------------------------------------------------------------------------
            //사용하는 쪽에서는 아래와 같이 사용한다.
            //
            //_Pdatabase->REC_Field_Read(0, _F_name_, NULL, &(_Pdatabase->tempstr));
            //
            //(void *) 로 인수를 받게 되 있으므로 원래 2 중 포인터로 처리할 것을 포인터 자체를
			//일단 (int) 로 변수로 바꾸고 다시 & 연산자로 [address] 를 념겨 주는 방식으로 처리한다.
            //}-------------------------------------------------------------------------------------

            //전달 받은 포인터에 직접 문자열이 있는 장소의 [address] 를 넘겨준다.
            *((int *)pDATA) = (int)(pRECORD->name);

            //또는, 아래와 같이 사용해도 무방하다.
            //*((int *)pDATA) = (int)(&(pRECORD->name[0]));

            return(true);

          }

    case  _F_index :
          {
            *((int *)pDATA) = pRECORD->index;
            return(true);

          }

    case  _F_kind :
          {
            *((int *)pDATA) = pRECORD->kind;
            return(true);

          }

    case  _F_area :
          {
            *((int *)pDATA) = pRECORD->area;
            return(true);

          }

    case  _F_typelistindex :
          {
            *((int *)pDATA) = pRECORD->typelistindex;
            return(true);

          }

    case  _F_filelistindex :
          {
            *((int *)pDATA) = pRECORD->filelistindex;
            return(true);

          }

    case  _F_pointer :
          {
            *((int *)pDATA) = pRECORD->pointer;
            return(true);

          }

    case  _F_motherindex :
          {
            *((int *)pDATA) = pRECORD->motherindex;
            return(true);

          }

    case  _F_arraydimension :
          {
            *((int *)pDATA) = pRECORD->arraydimension;
            return(true);

          }

    case  _F_arraysize :
          {
            //[주의!!!]{--------------------------------------------------------
            //(arraysize != NULL) 일 경우 arraysize[pFILEindex2] 로 사용한다.
            //arraysize[] 는 동적으로 생성되는 정보이므로 사전에 크기를 정의
            //할수 없기 떄문이다. 사전에 이미 저장 공간이 만들어져 있어야 한다.
            //}-----------------------------------------------------------------

            //[2005.11.07.월][추가!!!][중요!!!]{---------------
            //arraydimension 의 범위를 넘지 않있는지 확인한다.
            if(pRECORD->arraydimension <= pFIELDindex2)
            {
              //범위를 넘었으므로 error!!!
              return(false);

            }
            //}------------------------------------------------

            //[저장 공간 확인]
            //{
                //저장 공간이 만들어져 있는지 확인한다.
                if(pRECORD->arraysize == NULL)
                {
                  //아직 저장 공간이 없는 것이므로 저장 할수 없다!

                  //[size] 는 0 으로 반환한다.
                  *((int *)pDATA) = 0;

                  //아무 처리도 하지 않고 바로 종료한다.
                  return(false);

                }
            //}

            //지정값을 반환한다.
            *((int *)pDATA) = pRECORD->arraysize[pFIELDindex2];
            
            return(true);

          }

    case  _F_str :
          {
            //[2006.01.26.목][추가!!!]{---------------------------------------
            //문자열을 가지고 있는 memory[] 의 ponter 만 반환한다.
            //이미 문자열이 저장소에 있으므로 문자열 자체를 넘길 필요는 없다.
            //}---------------------------------------------------------------

            //[사용법]{-----------------------------------------------------------------------------
            //사용하는 쪽에서는 아래와 같이 사용한다.
            //char *strptr;
            //
            //_Pdatabase->REC_Field_Read(0, _F_str_, NULL, &(strptr));
            //
            //(void *) 로 인수를 받게 되 있으므로 원래 2 중 포인터로 처리할 것을 포인터 자체를
            //일단 (int) 로 변수로 바꾸고 다시 & 연산자로 [address] 를 념겨 주는 방식으로 처리한다.
            //}-------------------------------------------------------------------------------------

            //문자열이 NULL 인 경우도 문자열이 있는 것이므로 pointer 값이 존재하게 된다.
            //문자열이 없는 경우는 pointer 값 자체가 NULL 이된다.
            //그러므로 그냥 pointer 값을 반환하면 된다.
            //name[] 을 반환할때와 같은 경우가 된다.

            //[2012.04.20-1.목][주석처리!!!]
            /*
            //전달 받은 포인터에 직접 문자열이 있는 장소의 [address] 를 넘겨준다.
            *((int *)pDATA) = (int)(pRECORD->str_mem);
            */

            //[STRHEAP] 방식으로 변경.
            *((int *)pDATA) = (int)STRHEAP_Str_Ptr(&_strHeap, pRECORD->str_mem);

            return(true);

          }

    case  _F_size :
    {
      //[2008.11.05.수][추가!!!]

      *((long long *)pDATA) = pRECORD->size;
      return(true);

    } break;

    case  _F_address :
    {
      //[2008.11.05.수][추가!!!]

      *((unsigned long long *)pDATA) = pRECORD->address;
      return(true);

    } break;

  }

  //여기까지 온것은 해당하지 않는 것이므로 error!
  return(false);

}

bool __fastcall DATABASE::REC_Field_Read2(int   pRECORDindex,
                                          int   pFIELDindex1,
                                          int   pFIELDindex2,
                                          void *pDATA)
{
  //[2005.10.21.금][생성!!!]{-------------------------------------------------
  //REC_Field_Read 는 record 를 대상으로 하나, 이 함수는 record[] 의 index 로
  //직접 record[index] 로 작업 할수 있다.
  //}-------------------------------------------------------------------------

  return(REC_Field_Read(&(record[pRECORDindex]), pFIELDindex1, pFIELDindex2, pDATA));

}

bool __fastcall DATABASE::REC_Add(struct  RECORD *pRECORD,
                                  int            *pRECindex)
{
  //[2005.08.31.수][생성!!!]{-------------------------------------
  //{DATABASE} 의 가장 뒷 부분에 전달 받은 [record] 를 추가 한다.
  //[recordcount (base : 0)] 는 내부 적으로 자동으로 증가 시킨다.
  //[record] 추가시의 부가 처리도 같이 수행한다.
  //}-------------------------------------------------------------

  //[2005.10.27.목][수정!!!]{------------------------------------------------------
  //반환 값을 bool 에서 int 로 수정한다.
  //Add 시 저장된 record-index 를 반환해 주기 위한 것이며, 이는 미리 임시 레코드를
  //예약할떄 나중에 예약 위치에 다시 완성된 record 를 기록해 주기 위한 것이다.
  //}------------------------------------------------------------------------------

  //[반환값!!!]{---------------------------------------------------
  //(*pRECindex) 에 반환한다.
  // -1    : false 인 경우,
  // index : true 인 경우. 저장된 {DATABASE} 상의 record-index 값.
  //}--------------------------------------------------------------

  //[2005.09.05.월][추가!!!]{-------------------------
  //저장 공간의 크기를 넘지 않았는지 검사한다.
  if(record_count >= OPT_record_size)
  {
    (*pRECindex) = -1;
    return(false);

  }
  //}-------------------------------------------------

  //{DATABASE} 에 모든 값을 직접 copy 해 주어야 한다.
  record[record_count] = *(pRECORD);

  //기록된 record 수를 하나 증가 시켜준다.
  //이 값은 곧 다음에 저장될 record[] 의 index 위치도 된다.
  record_count++;

  //[!]{-------------------------------------------------------------------
  //무사히 처리되었으므로 {DATABASE} 상에 저장된 record-index 를 반환한다.
  //이미 증가한 count - 1 이 저장된 index 가 된다.
  (*pRECindex) = (record_count - 1);
  return(true);
  //}----------------------------------------------------------------------

}

/*
bool __fastcall DATABASE::REC_Delete(int  pDELETEindex)
{
  //[2005.09.04.일][생성!!!]{--------------------------------------------------
  //{DATABASE} 의 지정 위치의 [record] 를 하나 삭제한다.
  //실제로 삭제할 필요는 없고 도미노 처럼 뒤의 것을 앞으로 하나씩 copy
  //하면 간단하지만, record 안의 내용중 동적으로 생성된 pointer 부분(배열정보)
  //가 있으므로 동적으로 생성된 이 정보가 있다면 반드시 먼저 삭제해야 한다.
  //}--------------------------------------------------------------------------


  //[VAR]
  //{
      int  i;
  //}


  //[2005.10.17.월][추가!!!]{----------------------------------------------
  //먼저 삭제하려는 index 값이 저장된 index 범위를 넘지 않았는지 검사한다.
  if(!((0 <= pDELETEindex) && (pDELETEindex < record_count)))
  {
    //이 경우는 삭제하는 index 가 범위에 맞지 않으므로 error!!!
    return(false);

  }
  //}----------------------------------------------------------------------


  //먼저 삭제되는 record 내부에 있는 동적생성정보를 삭제한다.
  if(record[pDELETEindex].arraysize != NULL)
  {
    //내부에 동적으로 생성된 정보가 있는 경우만 처리한다.
    delete [] record[pDELETEindex].arraysize; record[pDELETEindex].arraysize = NULL;
  }


  //[2006.01.26.목][추가!!!]
  //동적 정보의 삭제.
  if(record[pDELETEindex].str_mem != NULL)
  {
    //내부에 동적으로 생성된 정보가 있는 경우만 처리한다.
    delete [] record[pDELETEindex].str_mem; record[pDELETEindex].str_mem = NULL;

  }


  for(i=pDELETEindex; i<(record_count-1); i++)
  {
    //뒤의 것을 앞으로 [copy] 해서 삭제된 record 를 매꾼다.
    record[i] = record[i+1];

  }


  //[record] 가 하나 줄었으므로 record 개수를 수정한다.
  record_count--;


  //여기까지 온것은 아무 이상없이 처리된 것이다.
  return(true);
  
}
*/

bool __fastcall DATABASE::REC_Insert(int             pINSERTindex,
                                     struct  RECORD *pRECORD)
{
  //[2005.09.04.일][생성!!!]{------------------------------------------
  //{DATABASE} 의 지정 위치에 [record] 를 하나 끼워 넣는다.
  //insert 는 delete 와는 달리 copy 하여 이동만 하는 것이므로
  //record 내부 동적 생성정보를 delete 할 필요는 없다.
  //먼저 끼워 넣을 자리의 정보를 뒤로 하나씩 밀어서 공간을 만든 다음에
  //이 공간에 record 를 집어 넣어야 한다.
  //}------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  //[2005.09.05.월][추가!!!]{---------------------------
  //저장 공간의 크기를 넘지 않았는지 검사한다.
  if(record_count > OPT_record_size) { return(false); }
  //}---------------------------------------------------

  //[공간 만들기]
  //{
      //먼저 끼워 넣을 공간을 만든다.
      for(i=pINSERTindex; i<(record_count-1); i++)
      {
        //한칸씩 뒤로 [copy] 한다.
        record[i+1] = record[i];

      }
  //}

  //마련 된 공간에 전달 받은 record 를 끼워 넣는다.
  record[pINSERTindex] = *(pRECORD);

  //insert 도 [record] 가 하나 늘어난 것이므로 record 개수를 하나 증가한다.
  record_count++;

  //여기까지 온것은 아무 이상 없는 것이다.
  return(true);

}

/*
bool __fastcall DATABASE::REC_Search_withName(int   pSTARTindex,
                                              char *pNAME,
                                              int  *pRECindex)
{
  //[2005.10.21.금][생성!!!]{--------------------------------------------------------
  //{DATABASE} 의 [name_field] 를 뒤져서 pNAME 과 일치하는 record-index 를 반환한다.
  //단, 처음부터 검색하는 것이 아니고 지정된 위치 pSTARTindex 부터 검사를 시작한다.
  //반환 값 -1 : 찾는 것이 없다는 뜻.
  //}--------------------------------------------------------------------------------

  //[VAR]
  //{
      int i;

  //}

  //[index 유효 검사]
  //{
      //[!]{-------------------------------------------------------------------------------
      //먼저 pSTARTindex 가 현재까지 {DATABASE} 에 저장된 index 범위 안에 있는지 검사한다.
      //}----------------------------------------------------------------------------------

      if(!((0 <= pSTARTindex) && (pSTARTindex < record_count)))
      {
        //지정 위치가 범위를 벘어났으므로 처리하지 않는다.
        (*pRECindex) = -1;
        return(false);

      }

  //}

  //[이름 찾기]
  //{
      //[!]{----------------------------------------------
      //{DATABASE} 상에서 같은 [이름] 이 있는지 검사한다.
      //}-------------------------------------------------

      for(i =  pSTARTindex; i < record_count; i++)
      {
        if(STR_Match(pNAME, record[i].name) == true)
        {
          //같은 이름을 찾은 것이다. 현재 record-index 를 반환한다.
          (*pRECindex) = i;
          return(true);

        }

      }
  //}

  //[!]{-----------------------------------------------------
  //여기까지 온것은 name 이 일치하는 record 가 없는 것이다.
  //}--------------------------------------------------------

  (*pRECindex) = -1;

  //찾지 못한 것이지 제대로 처리한것이므로 true 를 반환한다.
  return(true);

}
*/

bool __fastcall DATABASE::REC_Search_withNameAndArea(//검색 시작 위치.
                                                     int   pStartIndex,
                                                     //찾는 이름.
                                                     char *pName,
                                                     //대상 영역.
                                                     int   pArea,
                                                     //전체 {DATABASE} 를 대상으로 검사하는 경우는 true.
                                                     bool  pEntire,
                                                     //찾은 위치.
                                                     int  *rRecIndex)
{
  //[2009.03.26.목][생성!!!]{-------------------------------------------------------------------
  //[이름] 과 [영역] 을 전달 받아서 {DATABASE} 전체를 대상으로 일치하는 <record> 를 찾아서
  //해당 <record-index> 를 반환한다.
  //
  //[2009.03.28.토][수정!!!]--------------------------------------------------------------------
  //[인수] 에 [전체대상] 조건을 추가한다.
  //이는 [함수이름] 이나 [지역변수] 등의 경우는 [연속적] 이지 않을수 있으나 [구조체/공용체] 의
  //선언정보의 경우는 항상 연속적으로 존재하므로 굳이 전체를 대상으로 검사하는 경우 시간 낭비가
  //될수 있다. 따라서, [구조체/공용체] 의 경우는 전체를 대상으로 하지 않고 해당 [영역] 의
  //[시작 - [끝] 사이에서만 검사한다.
  //}-------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[index 유효 검사]
  //{
      //[!]{-------------------------------------------------------------------------------
      //먼저 pSTARTindex 가 현재까지 {DATABASE} 에 저장된 index 범위 안에 있는지 검사한다.
      //}----------------------------------------------------------------------------------

      if(!((0 <= pStartIndex) && (pStartIndex < record_count)))
      {
        //지정 위치가 범위를 벘어났으므로 처리하지 않는다.
        (*rRecIndex) = -1;
        return(false);

      }

  //}

  //[이름 찾기]
  //{
      //[!]{----------------------------------------------
      //{DATABASE} 상에서 같은 [이름] 이 있는지 검사한다.
      //}-------------------------------------------------

      for(i =  pStartIndex; i < record_count; i++)
      {
        //[영역] 이 일치 하는가?
        if(record[i].area == pArea)
        {
          //[이름] 이 일치 하는가?
          if(STR_Match(pName, record[i].name) == true)
          {
            //해당하는 것을 찾았다.
            (*rRecIndex) = i;
            return(true);

          }

        }
        else
        {
          //[2009.03.28.토][추가!!!]{--------------------------------------
          //[전체검색] 이 아닌 경우는 해당 영역을 넘은 경우 바로 종료한다.
          //}--------------------------------------------------------------

          if(pEntire != true)
          {
            if(record[i].area > pArea) break;

          }

        }

      }

  //}

  //[!]{-----------------------------------------------------
  //여기까지 온것은 name 이 일치하는 record 가 없는 것이다.
  //}--------------------------------------------------------

  (*rRecIndex) = -1;

  //찾지 못한 것이지 제대로 처리한것이므로 true 를 반환한다.
  return(true);

}

bool __fastcall DATABASE::REC_Search_withName_inFile(//검사를 시작할 record-index.
                                                     int   pSTARTindex,
                                                     //현재 문서 번호.
                                                     int   pFILELISTindex,
                                                     //검사할 단어.
                                                     char *pNAME,
                                                     //발견한 record-index.
                                                     int  *pRECindex)
{
  //[2005.10.21.금][생성!!!]{----------------------------------------------------------
  //{DATABASE} 의 [name_field] 를 뒤져서 pNAME 과 일치하는 record-index 를 반환한다.
  //단, 처음부터 검색하는 것이 아니고 지정된 위치 pSTARTindex 부터 검사를 시작한다.
  //반환 값 -1 : 찾는 것이 없다는 뜻.
  //{DATABASE} 전체에서 지정된 file 에 한정해서 찾는다.
  //{DATABASE} 의 record 에는 filelistindex 정보가 들어 있으므로 간단하게 찾을수 있다.
  //}----------------------------------------------------------------------------------

  //[VAR]
  //{
      int i;

  //}

  //[index 유효 검사]
  //{
      //[!]{-------------------------------------------------------------------------------
      //먼저 pSTARTindex 가 현재까지 {DATABASE} 에 저장된 index 범위 안에 있는지 검사한다.
      //}----------------------------------------------------------------------------------

      if(!((0 <= pSTARTindex) && (pSTARTindex < record_count)))
      {
        //지정 위치가 범위를 벘어났으므로 처리하지 않는다.
        (*pRECindex) = -1;
        return(false);

      }

  //}

  //[index 유효 검사]
  //{
      //[!]{----------------------------------------------------------------------------------
      //먼저 pFILELISTindex 가 현재까지 filelist[] 에 저장된 index 범위 안에 있는지 검사한다.
      //0 번 file 은 "GIGYEIN" file 로 이는 SYSTEM 예약이므로 사용해서는 안된다.
      //}-------------------------------------------------------------------------------------

      if(!((0 < pFILELISTindex) && (pFILELISTindex < filelist_count)))
      {
        //지정 위치가 범위를 벘어났으므로 처리하지 않는다.
        (*pRECindex) = -1;
        return(false);

      }

  //}

  //[검색]
  //{
      //[!]{-------------------------------------------
      //{DATABASE} 상에서 같은 이름이 있는지 검사한다.
      //}----------------------------------------------

      for(i = pSTARTindex; i < record_count; i++)
      {
        //[!]{-----------------------------------------
        //먼저 지정된 file 에 속한 <record> 를 찾는다.
        //}--------------------------------------------

        if(pFILELISTindex == record[i].filelistindex)
        {
          //같은 [이름] 을 찾는다.

          if(STR_Match(pNAME, record[i].name) == true)
          {
            //같은 [이름] 을 찾은 것이므로 현재 <record-index> 를 반환한다.

            (*pRECindex) = i;
            return(true);

          }

        }

      }
  //}

  //[!]{----------------------------------------------------
  //여기까지 온것은 name 이 일치하는 record 가 없는 것이다.
  //}-------------------------------------------------------

  (*pRECindex) = -1;

  //이상 없이 검색을 마쳤으므로 true.
  return(true);

}

bool __fastcall DATABASE::REC_Search_withName_inAllFile(//검색을 시작할 <record-index>.
                                                        int   pSTARTindex,
                                                        //문서 번호.
                                                        int   pFILELISTindex,
                                                        //검사할 [이름].
                                                        char *pNAME,
                                                        //찾은 <record-index>.
                                                        int  *pRECindex)
{
  //[2005.10.21.금][생성!!!]{----------------------------------------------------------------
  //{DATABASE} 의 [name_field] 를 뒤져서 pNAME 과 일치하는 record-index 를 반환한다.
  //단, 처음부터 검색하는 것이 아니고 지정된 위치 pSTARTindex 부터 검사를 시작한다.
  //반환 값 -1 : 찾는 것이 없다는 뜻.
  //
  //지정된 file 안에서의 검색은 REC_Search_withName_inFile() 함수를 사용한다.
  //이 함수는 하부 처리부에서 자신을 다시 호출하는 "재귀호출"을 사용한다.
  //
  //[중요점!!!]------------------------------------------------------------------------------
  //{DATABASE} 전체에서 지정된 file 에 한정해서 찾되, 지정된 file 에서 <include> 한 모든
  //file 을 다 뒤져서 검색한다. include 된 file 에서 다시 다른 file 을 include 하는 경우에도
  //전부 검색한다.
  //file 이 include 한 file 의 정보는 filelist[] 에 기록되 있다.
  //}----------------------------------------------------------------------------------------

  //[주의!!!]{---------------------------------------------------------------------------------------------
  //지정된 file 을 기본으로 검색을 하게 된다.
  //
  //[2005.10.24.월][추가!!!]
  //이 함수는 연속적으로 중복 사용될수 있으며, 이 경우는 LOCAL 변수의 경우 선언된 위치는 다르나,
  //이름은 같을수 있는데 이 경우 먼저 검색된 것이 NAME 은 같으나 해당하지 않는 경우 이 NAME 이 위치한
  //record-index 다음 record-index 와 현재 file 을 인수로 다시 전달 받아서 연속적으로 원하는것을
  //찾을때 까지 검사해 주어야 한다.
  //record 에는 해당 정보가 위치한 file 의 filelistindex 정보가 filed 정보로 기록되 있으므로
  //어떤 file 을 추가 처리 대상으로 할지를 쉽게 알수 있다.
  //
  //이는, 이 함수가 file 안에 포함된 모든 include file 을 대상으로 하고 이 include 된 file 안에 include 된
  //file 까지도 전부 대상으로 하므로 재 검색을 해야할 file 까지 알아야 할 필요가 있는 것이다.
  //그렇지 않으면 이미 검색한 것이 계속 검출될수 있다.
  //}------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int rec_index         = -1;
      int i                 =  0;
      int inc_count         =  0;
      int inc_filelistindex = -1;

  //}

  //[지정 문서에서 검색]
  //{
      //[검색]
      //{
          //우선 처음 인수로 지정된 [문서] 안에 존재하는지 검색한다.

          if(REC_Search_withName_inFile(pSTARTindex, pFILELISTindex, pNAME, &rec_index) == false)
          {
            (*pRECindex) = -1;

            //함수 error!!!
            return(false);

          }

      //}

      if(rec_index > -1)
      {
        //원하는 것을 찾은 것이므로 찾은 <record-index> 를 반환한다.

        (*pRECindex) = rec_index;
        return(true);
        
      }

  //}

  //[!]{-----------------------------------------------------------------------
  //여기까지 온것은 지정된 현재 file 에는 없는 것이므로, 이 file 이 include 한
  //file 안에 있는지 검사한다.
  //}--------------------------------------------------------------------------

  //[<include 문서> 존재 확인]
  //{
      //[!]{-------------------------------------------
      //이 file 에 include 한 [문서] 의 개수를 얻는다.
      //}----------------------------------------------

      inc_count = filelist[pFILELISTindex].include_list_count;

      //현재 이 file 안에 include 된 file 이 있는지 확인한다.
      if(inc_count <= 0)
      {
        //현재 file 에도 없고 이 file 이 include 한 file 이 없으므로 찾는것이 없다.
        (*pRECindex) = -1;

        //이상없이 검색을 마친 것이다.
        return(true);

      }

  //}

  //[<include> 된 [문서] 안에 존재하나?]
  //{
      //[중요!!!]{-------------------------------------------------------------
      //<include> 된 [문서] 안에 또다른 <include> 된 [문서] 가 있을수 있으므로
      //여기서는 REC_Search_withName_inFile() 함수가 아니고 지금 함수
      //REC_Search_withName_inAllFile() 함수를 재귀호출해서 사용해야 한다.
      //모든 <include> 된 [문서] 까지 완벽하게 검색하게 된다.
      //}----------------------------------------------------------------------

      //[!]{---------------------------------------------
      //바로 위에서 추출한 inc_count 정보를 사용한다.
      //현재 file 안에 include 된 file 만 대상으로 한다.
      //}------------------------------------------------

      for(i = 0; i < inc_count; i++)
      {
        //<include> 된 [문서] 의 <filelist-index> 를 구한다.
        inc_filelistindex = filelist[pFILELISTindex].include_list[i];

        //[검색]
        //{
            //[!]{-------------------------------------------------------------------
            //<include> 된 모든 [문서] 까지 검색한다.
            //<include> 된 [문서] 의 경우는 무조건 {DATABASE} 처음(0) 부터 검색한다.
            //}----------------------------------------------------------------------

            if(REC_Search_withName_inAllFile(0, inc_filelistindex, pNAME, &rec_index) == false)
            {
              (*pRECindex) = -1;
              return(false);

            }

            if(rec_index > -1)
            {
              //원하는 것을 찾은 것이다.

              (*pRECindex) = rec_index;
              return(true);

            }

        //}

      }

  //}

  //[!]{---------------------------------------------------
  //여기까지 온것은 include 된 모든 file 에도 없는 것이다.
  //}------------------------------------------------------

  (*pRECindex) = -1;

  //검색은 이상없이 마친것이다.
  return(true);

}

bool __fastcall DATABASE::REC_Search_withArea_Name_inAllFile(//검색 시작 <record-index>.
                                                             int   pSTARTindex,
                                                             //문서 번호.
                                                             int   pFILELISTindex,
                                                             //검색 영역 <record-index>.
                                                             int   pAREA,
                                                             //검색 [이름].
                                                             char *pNAME,
                                                             //찾은 <record-index>.
                                                             int  *pRECindex)
{
  //[2005.11.04.금][생성!!!]{----------------------------------------------------------------------
  //REC_Search_withName_inAllFile() 함수의 파생 함수로 AREA 정보까지 검색 조건에
  //추가하여 해당 [영역] 안의 것만을 대상으로 검색한다.
  //이는 IS_Name() 함수를 처리중 필요성이 있어서 만드는 것이다.
  //pAREA : -1 이면 global 이 되고 0 보다 큰 값은 해당 [영역 정보] 가 있는 <record-index> 가 된다.
  //}----------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int area;
      int rec_index   = 0;
      int start_index = 0;

      //[2006.01.28.목][추가!!!][중요!!!]{----------------------------------------
      //[이름] 이 발견된 <filelistindex> 를 저장한다.
      //이는 발견했으나 찾는 것이 아닌 경우 해당 문서의 [발견 지점 다음부터] 계속
      //찾아야 하고 이미 검사한 문서를 다시 검사하여 계속 찾은 것이 반복적으로
      //발견되어 [무한반복] 에 빠지는 것을 막기 위한 것이다.
      int start_filelistindex = -1;
      //}-------------------------------------------------------------------------

  //}

  //[!]{-------------------------------------------------------------------
  //일단 같은 [이름] 을 REC_Search_withName_inAllFile() 함수로 찾고,
  //그다음에 [영역] 이 일치하는 것을 찾아 해당 <record-index> 를 반환한다.
  //}----------------------------------------------------------------------

  //[2006.01.28.목][추가!!!][중요!!!]{----------------------------------------
  //지정된 문서를 다시 할당한다(사용하면서 값이 수정된 것이 반영되어야 한다).
  start_filelistindex =  pFILELISTindex;
  //}-------------------------------------------------------------------------

  while(1)
  {
    //[이름 검색]
    //{
        //같은 [이름] 에 해당하는 <record> 를 추출한다.
        if(REC_Search_withName_inAllFile(start_index,           //{DATABASE} 의 0 번 index 부터 검색한다.
                                         start_filelistindex,   //현재 처리중인 문서 번호.
                                         pNAME,                 //현재 검색하는 [이름].
                                         &rec_index) == false)
        {
          //함수 처리 오류!!!
          (*pRECindex) = -1;
          return(false);

        }

    //}

    if(rec_index > -1)
    {
      //일단 [이름] 이 같은 <record> 를 찾았다.

      //[영역 정보 추출]
      //{
          //같은 [영역] 인지 검사한다.

          if(REC_Field_Read2(rec_index, _F_area, NULL, &area) != true)
          {
            //함수 처리중 오류 가 발생한 것이므로 사용할수 없는 [이름] 으로 간주한다.

            (*pRECindex) = -1;
            return(false);

          }

      //}

      //[영역 비교]
      //{
          if(area == pAREA)
          {
            //같은 [영역] 이므로 찾은 <record-index> 를 반환한다.

            (*pRECindex) = rec_index;
            return(true);

          }
          else
          {
            //[!]{----------------------------------------------
            //아니라면 계속 같은 것이 있는지 검사한다.
            //같은 것이 없을때 까지 계속 검사해야 한다.
            //
            //[2006.01.28.토][수정!!!]{-------------------------
            //단, 찾은 <filelistindex> 부터 다시 검사해야 한다.
            //}-------------------------------------------------

            //[찾은 <filelistindex> 구하기][2006.01.28.토][추가!!!]{-----------------
            //이는 이미 검사한 [문서] 를 다시 검사하는 불상사를 막기 위한 것으로
            //단순하게 <record_index ++> 로 다음 위치로 이동하는 것만으로는 안되므로
            //금일 수정한다.
            start_filelistindex = record[rec_index].filelistindex;
            //}----------------------------------------------------------------------

            //[검사 시작 위치 설정]
            //{
                //[!]{-----------------------------------------------------------------------------
                //검색한 다음 <record> 위치 부터 검색을 시작 해야지 그렇지 않으면 현재 검색한 것이
                //다시 검색되게 되므로 주의한다.
                //}--------------------------------------------------------------------------------

                //[2006.02.15.수][수정!!!][주의!!!]
                //{
                    //[!]{----------------------------------------------------------------
                    //"rec_index < record_count" 이어야 하므로 이 규칙을 지켜야 한다.
                    //이렇게 하지 않는 경우 [라벨] 을 선언후 <goto> 를 바로 사용하는 경우
                    //검사시 {DATABASE} 의 [한계] 를 넘계되어 오류로 처리된다.
                    //}-------------------------------------------------------------------

                    if(rec_index < (record_count-1))
                    {
                      //증가 할수 있는 범위이다.

                      start_index = rec_index + 1;

                    }
                    else
                    {
                      //[!]{--------------------------------------------------------
                      //{DATABASE} 의 끝에 도달하였으므로 더이상 처리해서는 안된다.
                      //이 경우는 찾는 것이 없는 것으로 반환한다.
                      //}-----------------------------------------------------------

                      (*pRECindex) = -1;

                      //이상없이 검색을 마친것이다.
                      return(true);

                    }

                //}

            //}

            //계속 검색한다.
            continue;

          }

      //}

    }
    else
    {
      //찾는 것이 없으므로 [반복문] 을 종료한다.

      break;

    }

  }

  //[!]{-------------------------------------------
  //여기까지 온것은 검색결과 찾는 것이 없는것이다.
  //}----------------------------------------------

  (*pRECindex) = -1;

  //이상없이 검색을 마친것이다.
  return(true);

}

void __fastcall DATABASE::REC_GlobalData_EtcInfo(int   pRecIndex)
{
  //[2008.11.06.목][생성!!!]{-----------------------------------------
  //처리할 지정 rec_index 를 전달 받아서 이 record 가 [전역변수] 라면
  //size, address 정보를 구해서 저장해 준다.
  //
  //이 함수는 오직 [전역변수] 인 경우만을 대상으로 한다.
  //}-----------------------------------------------------------------


  if((record[pRecIndex].kind == _recKIND_data) &&  //DATA 인 경우인가? (순수 변수만 걸러내기 위한것)
     (record[pRecIndex].area == -1))               //[전역영역] 인가? (전역 변수만을 대상으로 해야 하므로)
  {
    //이 경우는 [전역변수] 인 경우이므로 size, address 를 구해준다.

    //[size 구하기]
    //{
        SIZE_Data(pRecIndex, &(record[pRecIndex].size));

    //}

    //[address 구하기]
    //{
        //현재 _DATA_ofsADR 값 이 지금 DATA 의 [추가주소] 가 된다.
        record[pRecIndex].address = _DATA_ofsADR;

        //다음 DATA 의 주소를 만들어 놓는다(현재 DATA 바로 다음이 된다).
        _DATA_ofsADR += record[pRecIndex].size;

    //}

  }

  return;

}

void __fastcall DATABASE::Rec_Size_Read(int         pRecIndex,
                                        long long  *rSize)
{
  //[2008.12.14.일][생성!!!]{-----------------------------------------------
  //{database}.size 정보를 읽어서 반환한다.
  //이는 복잡한 REC_Field_Read() 함수등을 사용하지 않고 바로 해당 하는 값만
  //얻기 위한 것이다.
  //}-----------------------------------------------------------------------

  (*rSize) = record[pRecIndex].size;

  return;

}

void __fastcall DATABASE::Rec_Address_Read(int                  pRecIndex,
                                           unsigned long long  *rAddress)
{
  //[2008.12.26.금][생성!!!]{-----------------------------------------------
  //{database}.address 정보를 읽어서 반환한다.
  //이는 복잡한 REC_Field_Read() 함수등을 사용하지 않고 바로 해당 하는 값만
  //얻기 위한 것이다.
  //}-----------------------------------------------------------------------

  (*rAddress) = record[pRecIndex].address;

  return;

}

//[FILELIST]--------------------------------------------------------------------

bool __fastcall DATABASE::FILELIST_Add(char *pFILEname,
                                       int   pFILEsize)
{
  //[2005.09.05.월][생성!!!]{-----------------
  //filelist[] 에 항목을 하나 추가한다.
  //내부적으로 count 를 증가 시켜주어야 한다.
  //}-----------------------------------------

  //[2005.09.12.월][수정!!!]{--------------------------------------------------
  //filelist[] 에는 같은 이름의 파일이 존재해서는 안되므로 무조건 추가하면
  //안되고 중복 검사를 해서 같은 것이 이미 있는 경우는 true 이나 또 추가하지는
  //않는다. 이는 include 문의 경우는 같은 file 을 계속 사용하게 되기 때문이다.
  //[주의!!!]
  //pFILEname 은 경로 전체를 가지고 있으므로 실제 [파일이름] 자체는 같더라도
  //경로가 다르면 filelist[] 상에서는 서로 다른 파일이 된다.
  //}--------------------------------------------------------------------------

  //[2005.10.13.목][주의!!!]{---------------------------------------------------
  //filename 의 경우는 대/소 문자를 구분하지 않으므로 중복 검사시 이를 감한해서
  //STR_Match_NoCase() 함수로 비교 검사를 해 주어야 한다.
  //}---------------------------------------------------------------------------


  //[VAR]
  //{
      int  i;

  //}


  //[2005.09.05.월][추가!!!]{--------------------------------------
  //저장 공간의 크기를 넘지 않았는지 검사한다.
  if(filelist_count >= OPT_file_name_list_size) { return(false); }
  //}--------------------------------------------------------------

  //전달 받은 pFILEname 이 중복되는지 검사한다.
  //현재까지 추가된 것만을 대상으로 한다.
  for(i=0; i<filelist_count; i++)
  {
    //[2005.10.13.목][수정!!!]{----------------------------------------
    //file 이름은 대/소 문자를 구분하지 않으므로 대/소 문자와 관계없이
    //검사할수 있는 STR_Match_NoCase() 함수를 사용한다.
    //}----------------------------------------------------------------

    if(STR_Match_NoCase(filelist[i].name, pFILEname) == true)
    {
      //filename 이 중복 되는 것이 있다면 true 이나, 추가하지는 않는다.
      //그냥 종료하면 된다.
      return(true);

    }
  }

  //[!]{-----------------------------------------------------------------
  //여기까지 온것은 pFILEname 이 중복되지 않는 새로운 것이므로 추가한다.
  //}--------------------------------------------------------------------

  //전달 받은 파일 이름(전체 경로 모두 포함)을 추가한다.
  STR_Assign(filelist[filelist_count].name, pFILEname);

  //전달 받은 파일 크기를 추가한다.
  filelist[filelist_count].size = pFILEsize;

  //count 를 증가시킨다.
  filelist_count++;

  //여기까지 온것은 이상 없는 것이다.
  return(true);

}

void __fastcall DATABASE::FILELIST_GetIndex_WithName(char *pFILEname,
                                                     int  *pINDEX)
{
  //[2005.09.12.월][생성!!!]{------------------------------------------------
  //filelist[] 에서 filename 을 가지고 해당 index 를 찾는다.
  //filelist[] 에는 같은 filename 은 존재하지 않으므로 일단 같은 filename 이
  //발견되면 바로 해당 index 를 반환하면 된다.
  //[반환값]
  //-1     : 해당하는 것이 존재하지 않는것.
  //0 이상 : 원하는 것을 찾은것.
  //}------------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  for(i=0; i<filelist_count; i++)
  {
    //[2005.10.13.목][수정!!!]{-------------------------------------------
    //filename 은 대/소 문자를 구분하지 않으므로 대/소 문자 구분없이 비교
    //할수 있는 STR_Match_NoCase() 함수를 사용한다.
    //}-------------------------------------------------------------------

    if(STR_Match_NoCase(filelist[i].name, pFILEname) == true)
    {
      //원하는 것을 찾은 것이므로 해당 index 를 반환한다.
      (*pINDEX) = i;

      return;

    }

  }

  //[!]{--------------------------------------------------------
  //여기까지 온것은 해당하는 것이 없는 것이므로 -1 을 반환한다.
  (*pINDEX) = -1;
  return;
  //}-----------------------------------------------------------

}

bool __fastcall DATABASE::FILELIST_GetName_WithIndex(int pINDEX,
                                                     char *pFILEname)
{
  //[2005.09.16.금][생성!!!]{-----------------------------------------
  //filelist[] 의 index 에 해당하는 filename 을 반환한다.
  //문자열 포인터를 전달받으므로 문자열을 완전히 copy 해 주어야 한다.
  //}-----------------------------------------------------------------

  //[index range check]
  //{
      //일단 index 가 현재 저장된 범위에 존재 하는지 확인한다.
      if(!((0<=pINDEX) && (pINDEX<filelist_count)))
      {
        //이 경우는 index 가 filelist[] 에 존재하지 않는 범위이므로 error!
        return(false);

      }
  //}

  //[filename]
  //{
      //해당 index 의 filename 을 copy 해서 반환한다.
      STR_Assign(pFILEname, filelist[pINDEX].name);
  //}

  //아무 이상없이 잘 처리된 것이다.
  return(true);

}

bool __fastcall DATABASE::FILELIST_GetSize_WithIndex(int  pINDEX,
                                                     int *pSIZE)
{
  //[2005.09.17.토][생성!!!]{------------
  //filelist[pINDEX].size 값을 반환한다.
  //0 : 찾는 것이 없는 경우.(error!!!)
  //}------------------------------------

  //[index range check]{-----------------------------------------------
  //일단 index 가 현재 저장된 범위에 존재 하는지 확인한다.
  if(!((0<=pINDEX) && (pINDEX<filelist_count)))
  {
    //이 경우는 index 가 filelist[] 에 존재하지 않는 범위이므로 error!
    (*pSIZE) = 0;

    //함수 error!!!
    return(false);

  }
  //}------------------------------------------------------------------

  //[filename]{-------------------------
  //해당 index 의 filesize 를 반환한다.
  (*pSIZE) = filelist[pINDEX].size;

  //무사히 함수 처리 완료!!!
  return(true);
  //}-----------------------------------

}

bool __fastcall DATABASE::FILELIST_Add_IncludeList(//[2012.04.08.일][추가!!!]
                                                   //오류 문자열 추가를 위한것.
                                                   class  DATABASE  *pDatabase,
                                                   int    pNowFileIndex,
                                                   int    pIncludeFileIndex)
{
  //[2005.10.12.수][생성!!!]{-------------------------------------------------------
  //"#include" 로 file 을 불러 들이는 경우, 불러 들인 file 의 filelist[] 상의
  //index 를 현재 file 의 filelist[].inc_filelistindex[] 에 저장해 놓는다
  //include 된것은 add 만 되므로 간단하게 추가하는 경우만 생각해 주면 된다.
  //
  //[주의!!!]{----------------------------------------------------------------------
  //현재 소스 파일에서 같은 file 을 중복하여 include 한 경우는 처음 include 시만
  //기록하고 동일한 나머지는 무시한다.
  //list 처리 용량을 넘어서서는 저장 할수 없으므로 이 경우는 error 로 간주한다.
  //
  //[참고!!!]{----------------------------------------------------------------------
  //이 함수를 사용하는 시점은 include 문이 있는 소스 파일안이므로 현재
  //parserinfo 정보 안에 현재 처리중인 filelistindex 가 이미 저장돼 있다.
  //
  //[주의!!!]{----------------------------------------------------------------------
  //이 함수는 #include 처리 부분에서 사용되며, filelist[] 정보를 처리 대상으로
  //하므로 반드시 filelist[] 에 정보가 추가된 다음에 사용해야 한다.
  //
  //[2012.04.07.토][중요수정!!!]----------------------------------------------------
  //<include> 한 문서만 기록하는 것이 아니라 이 문서가 <include> 한 문서와 다시
  //이 문서가 역시 <include> 한 모든 문서의 정보를 수집 관리.
  //
  //이를 위하여 <FILELIST:includeListTotal[]> 등 관련 변수 추가.
  //이는 <define> 선언된 것의 [영역유효] 여부를 구분하는데 보다 빠르게 하기 위한것.
  //실제 이 정보는 <DEFINELIST_Search_withName_Total()> 함수에서 사용된다.
  //<include> 는 호출 빈도가 낮기 때문에 이곳에서 처리하는 것이 전체 <Parser()>
  //속도에 영향을 주지 않으나, <define> 으로 정의된 단어를 처리하는데는 막대한
  //영향을 준다.
  //약 3배의 <Parser()>처리 속도의 향상이 있다.
  //
  //[2012.04.08.일][중요추가!!!]----------------------------------------------------
  //자신이 자신을 <include> 하는 경우는 오류로 간주.
  //A->B->A 등 상호 교차 <include> 의 경우는 <FILELIST_Add_IncludeListTotal()>,
  //<FILELIST_Add_IncludeListTotal2()> 함수에서 각각 처리된다.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[자신을 <include> 했나?]
  //{
      //[2012.04.08.일][중요추가!!!]{------
      //자신은 스스로 <include> 할수 없다.
      //}----------------------------------

      if(pNowFileIndex == pIncludeFileIndex)
      {
        if(pDatabase != NULL)
        {
          //[error message!!!]{---------------------------------------------
          pDatabase->ERRORINFO_Word("include");
          pDatabase->ERRORINFO_Add("자기 자신은 <include> 할수 없음!\r\n");
          //}---------------------------------------------------------------

        }

        return(false);

      }

  //}

  //[저장 가능상태 확인]
  //{
      //저장 할수 있는 상태인지 검사한다.
      if(filelist[pNowFileIndex].include_list_count >= OPT_include_list_size)
      {
        //이 경우는 관리 한도를 초과한 것이므로 오류.
        return(false);

      }

  //}

  //[중복검사]
  //{
      //[!]{--------------------------------------------------------
      //이미 <include_list[]> 에 존재하는 것이라면 추가하지 않는다.
      //현재 저장된 부분까지만 비교한다.
      //그러나, 중복된 것도 [유효] 한 것이므로 이상없는것.
      //}-----------------------------------------------------------

      for(i = 0; i < filelist[pNowFileIndex].include_list_count; i++)
      {
        if(filelist[pNowFileIndex].include_list[i] == pIncludeFileIndex)
        {
          //이 경우는 같은 것이 이미 존재하므로 저장하지 않는다.
          //그러나, 이상없는것.
          return(true);

        }

      }

  //}

  //[!]{------------------------------------------------------------------
  //여기까지 온것은 중복된 것이 없는 새로운 file 이므로 include_list[] 에
  //추가해 주어야 한다.
  //}---------------------------------------------------------------------

  //[추가]
  //{
      //현재 작업중인 file 의 include file list 에 include 된 fileindex 를 추가한다.
      filelist[pNowFileIndex].include_list[filelist[pNowFileIndex].include_list_count]
                             = pIncludeFileIndex;

      filelist[pNowFileIndex].include_list_count++;

  //}

  //[<includeListTotal[]> 관련 처리]
  //{
      //[2012.04.07.토][중요추가!!!]{-------------------------------------------------
      //1) <include> 된 [문서] 를 <include> 한 현재 문서역시 다른 문서에서
      //   <include> 되었을수 있으므로 거꾸로 거슬러 올라가면서 자신을 등록한
      //   다른 문서에 자신도 역시 등록해 준다.
      //   이는 더이상 다른 문서에 속해있지 않은 문서가 나올때 까지 계속 반복시킨다.
      //
      //2) A 가 B 를 <include> 한 경우 B 의 모든 <includeListTotal[]> 를 A 도 갖는다.
      //
      //이는 <define> 정의단어를 비교 처리시 보다 고속으로 처리하기 위한것.
      //
      //[주의!!!]---------------------------------------------------------------------
      //반드시 1), 2) 처리를 다 해주어야 한다.
      //이는 문서의 [포함관계] 와 처리 순서가 일치하지 않기 때문이다.
      //
      //[2012.04.08.일][추가!!!]------------------------------------------------------
      //이에 대한 설명은 <FILELIST_Add_IncludeListTotal2()> 함수안의 설명을 참고.
      //}-----------------------------------------------------------------------------

      //[(1) 처리]
      //{
          if(FILELIST_Add_IncludeListTotal(pDatabase, pNowFileIndex, pIncludeFileIndex) != true) return(false);

       //}

      //[(2) 처리]
      //{
          //현재 문서가 <include> 한 하위 문서가 가진 모든 문서도 등록.
          if(FILELIST_Add_IncludeListTotal2(pDatabase, pNowFileIndex, pIncludeFileIndex) != true) return(false);

      //}

  //}

  //여기까지 온것은 아무 이상없이 처리된 것이다.
  return(true);

}

bool __fastcall DATABASE::FILELIST_Add_IncludeListTotal(//[2012.04.08.일][추가!!!]
                                                        //오류 문자열 추가를 위한것.
                                                        class  DATABASE  *pDatabase,
                                                        //<include> 한 문서.
                                                        int    pNowFileIndex,
                                                        //<include> 된 문서.
                                                        int    pIncFileIndex)
{
  //[2012.04.07.토][생성!!!]{-----------------------------------------------------------
  //{ A->B->C->D } 순으로 계속 <include> 한 경우이고 현재 <pNowFileIndex:C> 인 경우라면
  //
  //1) D 문서를 C 의 <includeListTotal[]> 에 등록.
  //
  //2) C 를 직접 <include> 한 문서 B 를 <filelist[].include_list[]> 를 대상으로 찾기.
  //   이는 [직접 적인 1단계 포함] 만 검사하여 바로 위의 [문서] 만 찾으면 되기 때문.
  //
  //3) 2) 에서 찾은 문서의 <includeListTotal[]> 에 C 문서 등록.
  //   이는 해당하는 모든 문서에 동일하게 적용.
  //
  //4) 더이상 포함관계가 없는 문서가 나올때 까지 반복.
  //   함수 [재귀호출] 로 동일하게 처리.
  //
  //[참고!!!]---------------------------------------------------------------------------
  //이 함수는 <parser.cpp:Get_NextWord()> 함수에서 <define> [정의이름] 을 처리하는
  //<DEFINELIST_Search_withName_Total()> 함수를 위한 <includeListTotal[]> 정보를 수집.
  //결과적으로 <define> 정의이름 처리 속도가 3배 빨라진다.
  //
  //[2012.04.08.일][중요추가!!!]--------------------------------------------------------
  //자신을 자신의 <include> 목록에 등록할수 없다.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i, m;

      //자신을 포함한 상위문서 번호.
      int  momFileIndex;

  //}

  //[등록할 대상이 자기 자신인가?]
  //{
      //[2012.04.08.일][중요추가!!!]{------------
      //자신을 자신의 하위 문서로 등록할수 없다.
      //}----------------------------------------

      if(pNowFileIndex == pIncFileIndex)
      {
        if(pDatabase != NULL)
        {
          //[error message!!!]{---------------------------------------------------
          pDatabase->ERRORINFO_Word("include");
          pDatabase->ERRORINFO_Add("문서끼리는 서로를 <include> 할수 없음!\r\n");
          //}---------------------------------------------------------------------

          //[재귀호출] 되므로 계속 오류가 쌓이는 것을 방지 하기 위하여 NULL 로 초기화.
          pDatabase = NULL;

        }

        return(false);

      }

  //}

  //[저장 가능상태 확인]
  //{
      if(filelist[pNowFileIndex].includeListTotalCount >= OPT_IncludeListTotal_size)
      {
        //이 경우는 관리 한도를 초과.
        return(false);

      }

  //}

  //[중복검사]
  //{
      //[!]{------------------------------------------------------------
      //이미 <includeListTotal[]> 에 존재하는 것이라면 추가하지 않는다.
      //현재 저장된 부분까지만 비교한다.
      //그러나, [중복] 된 것도 유효한 것이므로 이상없는것.
      //}---------------------------------------------------------------

      for(m = 0; m < filelist[pNowFileIndex].includeListTotalCount; m++)
      {
        if(filelist[pNowFileIndex].includeListTotal[m] == pIncFileIndex)
        {
          //중복되는 경우는 [추가] 하지 않고 바로 다음으로 이동.
          //현재 <pIncFileIndex> 문서를 거꾸로 거슬러 올라가면서 등록해야 한다.
          goto lbMomFile;

        }

      }

      //[추가]
      //{
          //여기 까지 온것은 중복 되지 않는것이므로 추가.
          filelist[pNowFileIndex].includeListTotal[filelist[pNowFileIndex].includeListTotalCount]
                                 = pIncFileIndex;

          filelist[pNowFileIndex].includeListTotalCount++;

      //}

  //}

  lbMomFile:

  //[현재 문서를 <include> 한 상위문서 찾기]
  //{
      //[!]{------------------------------------------------------------------------
      //바로 1단계 위, 즉 현재 문서를 직접 <include> 한 문서만을 대상으로 처리.
      //
      //이 정보는 <include_list[]> 에 정확하게 이미 정리돼 있으므로 이 정보를 사용.
      //해당하는 모든 문서는 다 처리해 주어야 한다.
      //더이상 포함관계가 없는 최상위 문서가 나올때 까지 이 함수의 재귀호출로 처리.
      //}---------------------------------------------------------------------------

      for(i = 0; i < filelist_count; i++)
      {
        for(m = 0; m < filelist[i].include_list_count; m++)
        {
          //[현재 문서] 를 <include> 한 문서 찾기.
          if(filelist[i].include_list[m] == pNowFileIndex)
          {
            //[주의!!!]{----------------------------------------------------
            //<pNowFileIndex> 이 아니라 <pIncFileIndex> 을 등록하는 것이다.
            //}-------------------------------------------------------------

            //재귀호출로 처리.
            if(FILELIST_Add_IncludeListTotal(pDatabase, i, pIncFileIndex) != true) return(false);

          }

        }

      }

  //}

  return(true);

}

bool __fastcall DATABASE::FILELIST_Add_IncludeListTotal2(//[2012.04.08.일][추가!!!]
                                                         //오류 문자열 추가를 위한것.
                                                         class  DATABASE  *pDatabase,
                                                         //<include> 한 문서.
                                                         int    pNowFileIndex,
                                                         //<include> 된 문서.
                                                         int    pIncFileIndex)
{
  //[2012.04.07.토][생성!!!]{-----------------------------------------------------------
  //<include> 는 [Stack] 처럼 가장 마지막으로 include> 된 문서가 가장 먼저 등록된다.
  //문제는 이 경우 이 문서를 <include> 한 <*.c> 가 [설계묶음] 가장 마지막에 있어
  //<Parser()> 에서 가장 마지막에 처리되는 경우 결과적으로 가장 마지막에 등록되어
  //이 <*.c> 에서 <include> 한 문서가 자신을 호출한 문서에 자신을 등록할때
  //<*.c> 는 아직 <FILELIST> 에 등록이 안돼있어 [포함문서] 로 자신을 호출한 <*.c> 의
  //<includeListTotal[]> 에 등록할수 없게 된다.
  //즉, <FILELIST_Add_IncludeListTotal()> 함수만으로는 정확한 정보를 다 얻지 못한다.
  //따라서, <FILELIST_Add_IncludeListTotal()> 함수와 정 반대의 동작을 하는 함수가 필요.
  //
  //이 함수는 반대로 자신이 <include> 한 문서가 가진 모든 <includeListTotal[]> 정보를
  //자신의 <<includeListTotal[]>> 에 등록해준다.
  //이 경우 위와 같이 순서가 바뀌어도 정확한 [포함문서] 정보를 정리할수 있다.
  //
  //결론은, 두 함수다 사용되어야 한다는 점.
  //
  //[참고!!!]---------------------------------------------------------------------------
  //이 함수는 <parser.cpp:Get_NextWord()> 함수에서 <define> [정의이름] 을 처리하는
  //<DEFINELIST_Search_withName_Total()> 함수를 위한 <includeListTotal[]> 정보를 수집.
  //결과적으로 <define> 정의이름 처리 속도가 3배 빨라진다.
  //
  //[2012.04.08.일][중요추가!!!]--------------------------------------------------------
  //자신이 <include> 한 문서의 <include> 목록에 자신이 있어서는 안된다.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i, m;

  //}

  //[등록할 대상이 자기 자신인가?]
  //{
      //[2012.04.08.일][중요추가!!!]{------------
      //자신을 자신의 하위 문서로 등록할수 없다.
      //}----------------------------------------

      if(pNowFileIndex == pIncFileIndex)
      {
        if(pDatabase != NULL)
        {
          //[error message!!!]{---------------------------------------------------
          pDatabase->ERRORINFO_Word("include");
          pDatabase->ERRORINFO_Add("문서끼리는 서로를 <include> 할수 없음!\r\n");
          //}---------------------------------------------------------------------

        }

        return(false);

      }

  //}

  //[<include> 한 문서의 하위 문서 모두 등록]
  //{
      //[!]{-----------------------------------------------------------
      //현재 문서가 <include> 한 문서가 <include> 한 모든 문서를 추가.
      //단, [중복] 된 것은 추가로 등록하지 않는다.
      //}--------------------------------------------------------------

      for(i = 0; i < filelist[pIncFileIndex].includeListTotalCount; i++)
      {
        //현재 문서에 <pIncFileIndex> 문서가 가진 모든 문서 등록.
        for(m = 0; m < filelist[pNowFileIndex].includeListTotalCount; m++)
        {
          if     (filelist[pNowFileIndex].includeListTotal[m] ==
                  filelist[pIncFileIndex].includeListTotal[i])
          {
            //[중복] 되는 경우는 추가하지 않는다.
            continue;

          }
          //[2012.04.08.일][중요추가!!!]
          else if(pNowFileIndex == filelist[pIncFileIndex].includeListTotal[i])
          {
            //자신의 <include> 목록에 [자신] 을 등록하는 경우로 오류.

            if(pDatabase != NULL)
            {
              //[error message!!!]{---------------------------------------------------
              pDatabase->ERRORINFO_Word("include");
              pDatabase->ERRORINFO_Add("문서끼리는 서로를 <include> 할수 없음!\r\n");
              //}---------------------------------------------------------------------

            }

            return(false);

          }

        }

        //여기까지 온 것은 겹치지 않는것.

        //[추가]
        //{
            //여기 까지 온것은 중복 되지 않는것이므로 추가.
            filelist[pNowFileIndex].includeListTotal[filelist[pNowFileIndex].includeListTotalCount]
                                   = filelist[pIncFileIndex].includeListTotal[i];

            filelist[pNowFileIndex].includeListTotalCount++;

        //}

      }

  //}

  return(true);

}
  
/*
bool __fastcall DATABASE::FILELIST_Add_IncludeListTotal(//<include> 한 문서.
                                                        int   pNowFileIndex,
                                                        //<include> 된 문서.
                                                        int   pIncFileIndex)
{
  //[2012.04.07.토][생성!!!]{-----------------------------------------------------------
  //{ A->B->C->D } 순으로 계속 <include> 한 경우이고 현재 <pNowFileIndex:C> 인 경우라면
  //
  //1) D 문서를 C 의 <includeListTotal[]> 에 등록.
  //
  //2) C 를 직접 <include> 한 문서 B 를 <filelist[].include_list[]> 를 대상으로 찾기.
  //   이는 [직접 적인 1단계 포함] 만 검사하여 바로 위의 [문서] 만 찾으면 되기 때문.
  //
  //3) 2) 에서 찾은 문서의 <includeListTotal[]> 에 C 문서 등록.
  //   이는 해당하는 모든 문서에 동일하게 적용.
  //
  //4) 더이상 포함관계가 없는 문서가 나올때 까지 반복.
  //   함수 재귀호출로 동일하게 처리.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i, n;

      //자신을 포함한 상위문서 번호.
      int  momFileIndex;


  //}

  //[저장 가능상태 확인]
  //{
      if(filelist[pNowFileIndex].includeListTotalCount >= OPT_IncludeListTotal_size)
      {
        //이 경우는 관리 한도를 초과.
        return(false);

      }

  //}

  //[중복검사]
  //{
      //[!]{------------------------------------------------------------
      //이미 <includeListTotal[]> 에 존재하는 것이라면 추가하지 않는다.
      //현재 저장된 부분까지만 비교한다.
      //그러나, [중복] 된 것도 유효한 것이므로 이상없는것.
      //}---------------------------------------------------------------

      for(n = 0; n < filelist[pNowFileIndex].includeListTotalCount; n++)
      {
        if(filelist[pNowFileIndex].includeListTotal[n] == pIncFileIndex)
        {
          //중복되는 경우는 [추가] 하지 않고 바로 다음으로 이동.
          //현재 <pIncFileIndex> 문서를 거꾸로 거슬러 올라가면서 등록해야 한다.
          goto lbMomFile;

        }

      }

      //[추가]
      //{
          //여기 까지 온것은 중복 되지 않는것이므로 추가.
          filelist[pNowFileIndex].includeListTotal[filelist[pNowFileIndex].includeListTotalCount]
                                 = pIncFileIndex;

          filelist[pNowFileIndex].includeListTotalCount++;

      //}

  //}

  lbMomFile:

  //[현재 문서를 <include> 한 상위문서 찾기]
  //{
      //[!]{------------------------------------------------------------------------
      //바로 1단계 위, 즉 현재 문서를 직접 <include> 한 문서만을 대상으로 처리.
      //
      //이 정보는 <include_list[]> 에 정확하게 이미 정리돼 있으므로 이 정보를 사용.
      //해당하는 모든 문서는 다 처리해 주어야 한다.
      //더이상 포함관계가 없는 최상위 문서가 나올때 까지 이 함수의 재귀호출로 처리.
      //}---------------------------------------------------------------------------

      for(i = 0; i < filelist_count; i++)
      {
        for(n = 0; n < filelist[i].include_list_count; n++)
        {
          //[현재 문서] 를 <include> 한 문서 찾기.
          if(filelist[i].include_list[n] == pNowFileIndex)
          {
            //[주의!!!]{----------------------------------------------------
            //<pNowFileIndex> 이 아니라 <pIncFileIndex> 을 등록하는 것이다.
            //}-------------------------------------------------------------

            //재귀호출로 처리.
            if(FILELIST_Add_IncludeListTotal(i, pIncFileIndex) != true) return(false);

          }

        }

      }

  //}

  return(true);

}
*/

/*
bool __fastcall DATABASE::FILELIST_Add_IncludeList(int pNOWfileindex,
                                                   int pINCLUDEfileindex)
{
  //[2005.10.12.수][생성!!!]{-------------------------------------------------
  //"#include" 로 file 을 불러 들이는 경우, 불러 들인 file 의 filelist[] 상의
  //index 를 현재 file 의 filelist[].inc_filelistindex[] 에 저장해 놓는다
  //include 된것은 add 만 되므로 간단하게 추가하는 경우만 생각해 주면 된다.
  //}-------------------------------------------------------------------------

  //[주의!!!]{-------------------------------------------------------------------
  //현재 소스 파일에서 같은 file 을 중복하여 include 한 경우는 처음 include 시만
  //기록하고 동일한 나머지는 무시한다.
  //list 처리 용량을 넘어서서는 저장 할수 없으므로 이 경우는 error 로 간주한다.
  //}----------------------------------------------------------------------------

  //[idea!!!]{------------------------------------------------------------
  //이 함수를 사용하는 시점은 include 문이 있는 소스 파일안이므로 현재
  //parserinfo 정보 안에 현재 처리중인 filelistindex 가 이미 저장되 있다.
  //}---------------------------------------------------------------------

  //[사용!!!]{-----------------------------------------------------------------
  //이 함수는 #include 처리 부분에서 사용되며, filelist[] 정보를 처리 대상으로
  //하므로 반드시 filelist[] 에 정보가 추가된 다음에 사용해야 한다.
  //}--------------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  //[check!!!]
  //{
      //저장 할수 있는 상태인지 검사한다.
      if(filelist[pNOWfileindex].include_list_count >= OPT_include_list_size)
      {
        //이 경우는 관리 한도를 초과한 것이므로 error 이다.
        return(false);

      }
  //}

  //[중복검사]
  //{
      //이미 include_list[] 에 존재하는 것이라면 또 추가하지 않아야 한다.
      //현재 저장된 부분까지만 비교한다.
      //중복된 것도 유효한 것이므로 error 는 아니다.

      for(i = 0; i < filelist[pNOWfileindex].include_list_count; i++)
      {
        if(filelist[pNOWfileindex].include_list[i] == pINCLUDEfileindex)
        {
          //이 경우는 같은 것이 이미 존재하므로 저장하지 않는다.
          //그러나, error 는 아니므로 true 로 종료한다.
          return(true);

        }

      }
  //}

  //[!]{------------------------------------------------------------------
  //여기까지 온것은 중복된 것이 없는 새로운 file 이므로 include_list[] 에
  //추가해 주어야 한다.
  //}---------------------------------------------------------------------

  //[추가]
  //{
      //현재 작업중인 file 의 include file list 에 include 된 fileindex 를 추가한다.
      filelist[pNOWfileindex].include_list[filelist[pNOWfileindex].include_list_count]
                             = pINCLUDEfileindex;

      filelist[pNOWfileindex].include_list_count++;
  //}

  //여기까지 온것은 아무 이상없이 처리된 것이다.
  return(true);

}
*/

//[TYPELIST]--------------------------------------------------------------------

bool __fastcall DATABASE::TYPELIST_Add(char *pSTR,
                                       int   pRECindex,
                                       int  *rTYPELISTindex)
{
  //[2005.09.05.월][생성!!!]{-----------------
  //typelist[] 에 항목을 하나 추가한다.
  //내부적으로 count 를 증가 시켜주어야 한다.
  //}-----------------------------------------

  //[2005.10.31.월][대폭수정!!!]{-----------------------------------------------------
  //구조체/공용체 type 추가를 위한 구조체/공용체 type 선언정보가 있는 record-index 를
  //전달받아야 한다.(pRECindex)
  //type 에 대한 자세한 정보를 전달 받아야 하는 경우 이 index 정보를 참고할수 있다.
  //}---------------------------------------------------------------------------------

  //[2006.01.12.목][추가!!!]{------------------------------
  //pTYPELISTindex : typelist[] 에 저장된 위치를 넘겨준다.
  //}------------------------------------------------------

  //[2005.09.05.월][추가!!!]{---------------------------------
  //저장 공간의 크기를 넘지 않았는지 검사한다.
  if(typelist_count >= OPT_type_list_size) { return(false); }
  //}---------------------------------------------------------

  //[문자열 저장]
  //{
      //전달 받은 [type] 문자열을 저장한다.
      STR_Assign(typelist[typelist_count].type, pSTR);
  //}

  //[record-index]
  //{
      //[2005.10.31.월][추가!!!]
      //record-index 정보를 저장한다.
      typelist[typelist_count].rec_index = pRECindex;
  //}

  //[2007.07.20.금][수정!!!]
  //NULL 인 경우는 굳이 처리할 필요는 없다.
  if(rTYPELISTindex != NULL)
  {
    //[2006.01.12.목][추가!!!]
    //{
        //현재 type 이 추가된 typelist[] 상의 index 를 반환한다.
        //이는 [구조체/공용체 type] 선언 처리 부에서 선언과 동시 data 를 선언하는 경우
        //type 을 알아야 하는데 이때 필요하다.
        (*rTYPELISTindex) = typelist_count;
    //}

  }

  //[count]
  //{
      //count 를 중가한다.
      typelist_count++;
  //}

  //여기까지 온것은 아무 이상 없는 것이다.
  return(true);

}

bool __fastcall DATABASE::TYPELIST_Set_Size(int        pTYPELISTindex,
                                            long long  pTYPEsize)
{
  //[2007.07.20.금][생성!!!]{-----------
  //해당 type 의  size 정보를 기록한다.
  //}-----------------------------------

  //[검사!!!]
  //{
      //저장 공간의 크기를 넘지 않았는지 검사한다.
      if(pTYPELISTindex >= typelist_count) { return(false); }
  //}

  //[size]
  //{
      //크기정보를 기록한다.
      typelist[pTYPELISTindex].size = pTYPEsize;
  //}

  //여기까지 온것은 아무 이상 없는 것이다.
  return(true);

}

void __fastcall DATABASE::TYPELIST_GetTypeIndex_withNAME(char *pTYPE,
                                                         int  *pINDEX)
{
  //[2005.11.1.화][생성!!!]{-------------------------------------
  //전달 받은 pTYPE 와 같은 이름의 것을 typelist[] 상에서 찾아서
  //해당 index 를 반환한다.
  //찾는 것이 없는 경우는 -1 을 반환한다.
  //}------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  for(i = 0; i < typelist_count; i++)
  {
    if(STR_Match(typelist[i].type, pTYPE) == true)
    {
      //같은 것을 찾았으므로 해당 index 를 반환한다.
      (*pINDEX) = i;

      return;

    }

  }

  //여기까지 온것은 같은 것을 찾지 못한 것이다.
  (*pINDEX) = -1;
  
  return;

}

bool __fastcall DATABASE::TYPELIST_IS_IntType(int pTYPELISTINDEX)
{
  //[2006.02.16.목][작성!!!]{----------------------------------------------
  //전달받은 typelistindex 값이 [정수] 형인 경우는 true 를 반환한다.
  //현재 아래와 같은 순서로 쌓여 있으므로 이 범위의 index 안에 있다면
  //무조건 [정수] 로 볼수 있다.
  //만일 typelist[] 에 저장되는 순서를 바꾼다면 이것도 수정해 주어야 한다.
  //[1]		signed	-1
  //[2]		unsigned	-1
  //[3]		signed char	-1
  //[4]		signed short	-1
  //[5]		signed int	-1
  //[6]		signed long	-1
  //[7]		unsigned char	-1
  //[8]		unsigned short	-1
  //[9]		unsigned int	-1
  //[10]	unsigned long	-1
  //[11]	char	-1
  //[12]	short	-1
  //[13]	int	-1
  //[14]	long	-1
  //}----------------------------------------------------------------------

  //현재는 (1 <= index <= 14) 의 범위에 있다면 [정수] 로 본다.
  if((c_int_type_first_typelistindex <= pTYPELISTINDEX) && (pTYPELISTINDEX <= c_int_type_last_typelistindex))
  {
    //이 경우는 [정수] 로 본다.
    return(true);

  }

  //여기까지 온것은 [정수] 에 해당하지 않는 type 이다.
  return(false);

}

bool __fastcall DATABASE::TYPELIST_IS_FloatType(int pTYPELISTINDEX)
{
  //[2006.08.12.토][작성!!!]{----------------------------------------------
  //전달받은 typelistindex 값이 [실수] 형인 경우는 true 를 반환한다.
  //현재 아래와 같은 순서로 쌓여 있으므로 이 범위의 index 안에 있다면
  //무조건 [실수] 로 볼수 있다.
  //만일 typelist[] 에 저장되는 순서를 바꾼다면 이것도 수정해 주어야 한다.
  //[15]   float
  //[16]   double
  //}----------------------------------------------------------------------

  //현재는 (15 <= index <= 16) 의 범위에 있다면 [정수] 로 본다.
  if((c_float_type_first_typelistindex <= pTYPELISTINDEX) && (pTYPELISTINDEX <= c_float_type_last_typelistindex))
  {
    //이 경우는 [실수] 로 본다.
    return(true);

  }

  //여기까지 온것은 [실수] 에 해당하지 않는 type 이다.
  return(false);

}

bool __fastcall DATABASE::TYPELIST_IS_StructType(int pTYPELISTindex)
{
  //[2006.04.19.수][생성!!!]{------------------------------------------------------
  //전달받은 typelistindex 값으로 이 type 이 순순한 [구조체] type 인지 확인해준다.
  //}------------------------------------------------------------------------------


  //[VAR]
  //{
      int   record_index  = 0;
      int   record_kind   = 0;
  //}


  if((c_type_last_typelistindex < pTYPELISTindex) && (pTYPELISTindex < typelist_count))
  {
    //일단 [구조체/공용체] type 에는 해당하는 것이다.
    //순수한 [구조체] type 인지 확인한다.

    //[구조체 type 인가?]
    //{
        //----------------------------------------------------------------------------
        //해당 type 이 선언된 {DATABASE} 상의 record-index 를 얻는다.
        record_index = typelist[pTYPELISTindex].rec_index;

        //record 의 종류가 _recKIND_structtype 라면 [구조체] 선언 record 에 해당한다.
        REC_Field_Read2(record_index, _F_kind, NULL, &record_kind);

        if(record_kind == _recKIND_structtype)
        {
          //순수한 [구조체 type] 으로 볼수 있다.
          return(true);

        }
        //----------------------------------------------------------------------------
    //}
  }

  //여기까지 온것은 이 typelistindex 의 type 은 순수한 [구조체] type 에
  //해당하지 않는 것이다.
  return(false);

}

bool __fastcall DATABASE::TYPELIST_IS_UnionType(int pTYPELISTindex)
{
  //[2006.04.19.수][생성!!!]{------------------------------------------------------
  //전달받은 typelistindex 값으로 이 type 이 순순한 [공용체] type 인지 확인해준다.
  //}------------------------------------------------------------------------------


  //[VAR]
  //{
      int   record_index  = 0;
      int   record_kind   = 0;
  //}


  if((c_type_last_typelistindex < pTYPELISTindex) && (pTYPELISTindex < typelist_count))
  {
    //일단 [구조체/공용체] type 에는 해당하는 것이다.
    //순수한 [구조체] type 인지 확인한다.

    //[공용체 type 인가?]
    //{
        //---------------------------------------------------------------------------
        //해당 type 이 선언된 {DATABASE} 상의 record-index 를 얻는다.
        record_index = typelist[pTYPELISTindex].rec_index;

        //record 의 종류가 _recKIND_uniontype 라면 [공용체] 선언 record 에 해당한다.
        REC_Field_Read2(record_index, _F_kind, NULL, &record_kind);

        if(record_kind == _recKIND_uniontype)
        {
          //순수한 [공용체 type] 으로 볼수 있다.
          return(true);

        }
        //---------------------------------------------------------------------------
    //}
  }

  //여기까지 온것은 이 typelistindex 의 type 은 순수한 [공용체] type 에
  //해당하지 않는 것이다.
  return(false);

}

bool __fastcall DATABASE::TYPELIST_IS_C_DataType(int pTYPELISTINDEX)
{
  //[2006.04.19.수][생성!!!]{---------------------------------------------
  //typelist[] 를 검사하여 순수한 ANSI-C 의 기본 data type 인지 확인한다.
  //}---------------------------------------------------------------------


  if((c_type_first_typelistindex <= pTYPELISTINDEX) && (pTYPELISTINDEX <= c_type_last_typelistindex))
  {
    //[ANSI-C] 기본 data type 에 해당한다.
    return(true);

  }

  //여기까지 온것은 [ANSI-C] 기본 data type 에 해당 하지 않는 것이다.
  return(false);

}

int __fastcall DATABASE::TYPELIST_Get_Count(void)
{
  //[2006.04.14.금][생성!!!]{-----
  //typelist_count 값을 반환한다.
  //}-----------------------------

  return(typelist_count);

}

int __fastcall DATABASE::TYPELIST_Get_RecIndex(int pTYPELISTindex)
{
  //[2006.04.15.토][생성!!!]{-------------------------
  //typelist[] 상의 저장된 recordindex 값을 반환한다.
  //}-------------------------------------------------

  return(typelist[pTYPELISTindex].rec_index);

}

long long __fastcall DATABASE::TYPELIST_Get_Size(int pTYPELISTindex)
{
  //[2007.07.20.금][생성!!!]{-------------
  //typelist[] 상의 size 정보를 반환한다.
  //}-------------------------------------

  return(typelist[pTYPELISTindex].size);

}

bool __fastcall DATABASE::TYPELIST_Get_IntegerTypeName(int   pTypelistIndex,
                                                       char  rTypeName[])
{
  //[2008.10.21.화][생성!!!]{-----------------------------------------------------------------------
  //정수 type 에 해당하는 경우만 처리 하며 같은 계통인 경우는 해당 대표 [type 이름] 을 반환해 준다.
  //검사하는 type 이 이 함수처리 대상이 아닌 경우는 false 를 반환한다.
  //}-----------------------------------------------------------------------------------------------

  //[현재 type 정의 고정 위치]
  //{
      //[11]  char          	-1
      //[3 ]  signed char	-1
      //[7 ]  unsigned char	-1

      //[12]  short     	-1
      //[4 ]  signed short	-1
      //[8 ]  unsigned short	-1

      //[1 ]  signed	        -1
      //[2 ]  unsigned	        -1
      //[13]  int               -1
      //[5 ]  signed int	-1
      //[9 ]  unsigned int	-1


      //[14]  long         	-1
      //[6 ]  signed long	-1
      //[10]  unsigned long	-1

      //위의 고정 위치를 바탕으로 char, short, int, long 인지만 구분하면 된다.

  //}


  switch(pTypelistIndex)
  {
    case 11 :
    case 3  :
    case 7  :
    {
      //char 인 경우.

      STR_Assign(rTypeName, "char");

      return(true);

    } break;

    case 12 :
    case 4  :
    case 8  :
    {
      //short 인 경우.

      STR_Assign(rTypeName, "short");

      return(true);

    } break;

    case 1  :
    case 2  :
    case 13 :
    case 5  :
    case 9  :
    {
      //int 인 경우.

      STR_Assign(rTypeName, "int");

      return(true);

    } break;

    case 14 :
    case 6  :
    case 10 :
    {
      //long 인 경우.

      STR_Assign(rTypeName, "long");

      return(true);

    } break;

    //위의 고정 위치를 바탕으로 char, short, int, long 인지만 구분하면 된다.

  }

  //[반환]
  //{
      STR_Assign(rTypeName, "");

      //여기까지 온것은 이 함수처리에 해당하지 않는 것이다.
      return(false);

  //}

}

bool __fastcall DATABASE::TYPELIST_Is_Family(int  pTypelistIndexA,
                                             int  pTypelistIndexB)
{
  //[2008.10.21.화][생성!!!]{-------------------------------------------------------------------------
  //두개의 [type] 이 같은 계통인지 확인한다.
  //즉, signed int, unsigned int, int 는 모두 같은 크기를 갖으므로 같은 것으로 본다.
  //이는 같은 계통의 경우 push, pop 의 경우 크기만 중요하므로 1차 번역시 효율성을 높이기 위한 것이다.
  //같은 계통인 경우는 true 를 반환한다.
  //단, 여러 가지로 계통을 가지는 정수만 해당하고 float, double 등은 해당하지 않는다.
  //}-------------------------------------------------------------------------------------------------


  //[VAR]
  //{
      char typeNameA[OPT_name_length],
           typeNameB[OPT_name_length];

  //}

  //[각각의 type 이름 구하기]
  //{
      if(TYPELIST_Get_IntegerTypeName(pTypelistIndexA, typeNameA) != true) return(false);
      if(TYPELIST_Get_IntegerTypeName(pTypelistIndexB, typeNameB) != true) return(false);

  //}

  //[같은 계통인가?]
  //{
      //같은 계통이라면 [type 이름] 이 일치하면 된다.

      if(STR_Match(typeNameA, typeNameB) == true)
      {
        //같은 계통이다.
        return(true);

      }

  //}

  //여기까지 온것은 같은 계통이 아닌 것이다.
  return(false);

}

bool __fastcall DATABASE::TYPELIST_Is_Unsigned(int  pTypelistindex)
{
  //[2008.12.25.목][생성!!!]{------------------------------
  //"unsigned" 인 경우인지만 확인한다.
  //"unsigned" 를 제외한 경우는 전부 "signed" 로 취급한다.
  //}------------------------------------------------------

  switch(pTypelistindex)
  {
    case 0 :  case 2 :  case 7 : case 8 : case 9 : case 10 :
    {
      //"unsigned" 에 해당하는 것으로 본다.
      return(true);

    }

  }

  //여기까지 온것은 "unsigned" 에 해당하지 않는 것으로 간주한다.
  return(false);

}

CTYPEETCINFO DATABASE::CTYPE_Get_EtcInfo(int pTYPELISTindex)
{
  //[2006.04.22.토][생성!!!]{-----------------------------------------------
  //typelist[] 의 정보를 참고하여 순수 C-data-type 의 부가 정보를 추출한다.
  //
  //[1 BYTE 정보]
  //bit[0~3] 의 값이 1 ~ 8 까지 크기.
  //bit[4] (1:signed) (0:unsigned)
  //bit[5] (1:실수) (0:정수)
  //}-----------------------------------------------------------------------

  //[주의!!!]{----------------------------------
  //typelist[] 상의 저장순서와 직접관련이 있다.
  //순서가 바뀌지 않도록 주의해야 한다.
  //}-------------------------------------------


  //[VAR]
  //{
      CTYPEETCINFO etcinfo = 0;
  //}


  switch(pTYPELISTindex)
  {
    case  0 : //void
    {
      etcinfo = 0 | 0 | 0;

    } break;

    case  1 : //signed
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 4;

    } break;

    case  2 : //unsigned
    {
      etcinfo = 0 | 0 | 4;

    } break;

    case  3 : //signed char
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 1;

    } break;

    case  4 : //signed short
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 2;

    } break;

    case  5 : //signed int
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 4;

    } break;

    case  6 : //signed long
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 8;

    } break;

    case  7 : //unsigned char
    {
      etcinfo = 0 | 0 | 1;

    } break;

    case  8 : //unsigned short
    {
      etcinfo = 0 | 0 | 2;

    } break;

    case  9 : //unsigned int
    {
      etcinfo = 0 | 0 | 4;

    } break;

    case 10 : //unsigned long
    {
      etcinfo = 0 | 0 | 8;

    } break;

    case 11 : //char
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 1;

    } break;

    case 12 : //short
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 2;

    } break;

    case 13 : //int
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 4;

    } break;

    case 14 : //long
    {
      etcinfo = 0 | ctypeETCinfo_sign1 | 8;

    } break;

    case 15 : //float
    {
      etcinfo = ctypeETCinfo_if1 | ctypeETCinfo_sign1 | 8;

    } break;

    case 16 : //double
    {
      etcinfo = ctypeETCinfo_if1 | ctypeETCinfo_sign1 | 8;

    } break;

    default :
    {
      etcinfo = 0 | 0 | 0;

    } break;
  }

  //조합된 장보를 반환한다.
  return(etcinfo);

}

int DATABASE::CTYPE_Get_Bigger_TypeListIndex(CTYPEETCINFO pAtype,
                                             CTYPEETCINFO pBtype)
{
  //[2006.04.23.일][생성!!!]{---------------------------------------
  //A, B 의 type 정보는 얻어서 보다 큰 type 을 조합하고, 이 type 의
  //typelistindex 를 반환한다.
  //}---------------------------------------------------------------


  //[VAR]
  //{
      char typeword[OPT_name_length] = {""};
      int  size = 0;
      int  typelistindex = -1;
  //}


  //[float]
  //{
      //-------------------------------------------------------------
      //둘중 하나라도 [실수] 라면 실수가 된다.
      if((pAtype & ctypeETCinfo_if1) || (pBtype & ctypeETCinfo_if1))
      {
        //실수인 경우는 무조건 double 이 된다.
        STR_Add(typeword, "double");

        //이미 모든 것이 결정되었으므로 바로 종료한다.
        goto END;

      }
      //-------------------------------------------------------------
  //}

  //[sign]
  //{
      //-----------------------------------------------------------------
      //둘중 하나라도 "signed" 라면 "signed" 로 간주한다.
      if((pAtype & ctypeETCinfo_sign1) || (pBtype & ctypeETCinfo_sign1))
      {
        STR_Add(typeword, "signed");
        STR_Add(typeword, " ");

      }
      else
      {
        STR_Add(typeword, "unsigned");
        STR_Add(typeword, " ");

      }
      //-----------------------------------------------------------------
  //}

  //[type]
  //{
      //-----------------------------------------------------------------
      //A, B 중 보다 큰 type 의 것을 사용 한다.
      if((pAtype & ctypeETCinfo_size4) >= (pBtype & ctypeETCinfo_size4))
      {
        //A 의 크기를 사용한다.
        size = pAtype & ctypeETCinfo_size4;

      }
      else
      {
        //B 의 크기를 사용한다.
        size = pBtype & ctypeETCinfo_size4;

      }
      //-----------------------------------------------------------------
  //}

  //[정수 type 합성]
  //{
      //------------------------------------------------------------------
      //여기까지 온것은 이미 [정수] 만 해당하는 것이므로 [크기] 에 따라서
      //해당 type 을 계속 합성해 준다.
      switch(size)
      {
        case 1 :
        {
          STR_Add(typeword, "char");

        } break;

        case 2 :
        {
          STR_Add(typeword, "short");

        } break;

        case 4 :
        {
          STR_Add(typeword, "int");

        } break;

        case 8 :
        {
          STR_Add(typeword, "long");

        } break;
      }
      //------------------------------------------------------------------
  //}


  END:


  //[typelistindex]
  //{
      //--------------------------------------------------------------------
      //원하는 type 의 [문자열] 이 모두 조합되었으므로 [문자열] 에 해당하는
      //typelistindex 값을 구한다.
      TYPELIST_GetTypeIndex_withNAME(typeword, &typelistindex);
      //--------------------------------------------------------------------
  //}

  //추출한 typeistindex 값을 반환한다.
  return(typelistindex);

}

int DATABASE::CTYPE_TypeListIndex(int pAtypelistindex,
                                  int pBtypelistindex)
{
  //[2006.04.24.월][생성!!!]{---------------------------------------------
  //typelistindex 두개를 전달 받아서 둘중 더 큰 type 을 추출하고 해당되는
  //typelistindex 를 반환한다.
  //}---------------------------------------------------------------------


  //[VAR]
  //{
      CTYPEETCINFO  etcinfoA      = 0,
                    etcinfoB      = 0;
      int           typelistindex = -1;
  //}


  //[etcinfo]
  //{
      //---------------------------------------------
      //각각의 etcinfo 를 얻는다.
      etcinfoA = CTYPE_Get_EtcInfo(pAtypelistindex);
      etcinfoB = CTYPE_Get_EtcInfo(pBtypelistindex);
      //---------------------------------------------
  //}

  //[bigger]
  //{
      //------------------------------------------------------------------
      //보다 큰 type 을 얻는다.
      typelistindex = CTYPE_Get_Bigger_TypeListIndex(etcinfoA, etcinfoB);
      //------------------------------------------------------------------
  //}

  return(typelistindex);

}

//[SIZE]------------------------------------------------------------------------

void __fastcall DATABASE::SIZE_Data(int         pRECindex,
                                    long long  *rSIZE)
{
  //[2007.07.21.토][생성!!!]{-----------------------------------------------
  //{database} 상의 recindex 에 해당하는 data 의 byte 단위 크기 정보를
  //구해서 반환한다.
  //가장 일반적인 함수로써 모든 종류가 다 포함된다.
  //단, [구조체/공용체] 선언 type 을 여기서 처리하지 않는다.
  //순수하게 선언된  data 만 대상으로 한다.
  //이미 선언된 [구조체/공용체] 의 경우도 typelist[] 상에 해당 type 의 크기
  //정보가 들어 있으므로 해당 크기를 구할수 있다.
  //}-----------------------------------------------------------------------

  //[설명]
  //{
      //[배열] 의 경우는 전용 함수로 처리하고, [포인터] 의 경우는 무조건
      //[주소변수] 가 되어 64bit(8byte) 크기를 갖는다.
      //다른것은 자신의 해당 type 의 크기를 갖는다.
  //}


  //[VAR]
  //{
      int  typelistindex;

  //}


  if     (record[pRECindex].arraydimension > 0)
  {
    //[배열이름]

    //[배열 인수 구분 처리]
    //{
        //[2008.11.02.일][중요추가!!!]{----------------------------------------------------------
        //[인수] 에 [배열형식] 이 사용된 경우는 실제 메모리 상의 배열 선언이 아니라 형식만
        //정의한 것이므로 실제는 포인터가 된다.
        //함수 내부적으로 인수를 배열로 사용하기 위한 정의일 뿐이다.
        //따라서, 이 경우는 [인수] 의 크기는 배열이름(포인터) 의 크기 8 byte 가 된다.
        //배열이 인수에 사용된 경우는 [배열이름] 이 [상수포인터] 가 아니라 [변수포인터] 가 된다.
        //
        //단, 이 경우는 [인수] 에 [배열] 이 사용된 경우가 유일하다. 다른 경우는 [인수] 는 전부
        //해당 크기를 가지는 [지역변수] 가 된다.
        //}--------------------------------------------------------------------------------------

        if(record[pRECindex].kind == _recKIND_func_param)
        {
          //단지 포인터가 된다.
          (*rSIZE) = 8;

        }
        else
        {
          //순수한 [배열] 인 경우.

          //전용 함수로 처리한다.
          SIZE_Array(pRECindex, rSIZE);

        }

    //}

  }
  else if(record[pRECindex].pointer > 0)
  {
    //[포인터]

    //절대 주소(64bit)를 저장하므로 무조건 8byte 가 된다.
    (*rSIZE) = 8;

  }
  else
  {
    //[일반 DATA]

    //변수, 구조체, 공용체 등이 해당한다.
    //해당 type 크기를 반환한다.

    //[typelistindex 얻기]
    //{
        typelistindex = record[pRECindex].typelistindex;
    //}

    //[typesize 얻기]
    //{
        (*rSIZE) = TYPELIST_Get_Size(typelistindex);
    //}

  }

  return;

}

void __fastcall DATABASE::SIZE_Array(int         pRECindex,
                                     long long  *rSIZE)
{
  //[2007.07.21.토][생성!!]{---------------------------------------------------------
  //[배열이름] 의 경우는 선언된 차원과 크기 정보를 참고로 정확한 크기를 구해야 한다.
  //다른 data 에 비하여 처리가 복잡하므로 이 전용 함수를 만든다.

  //즉. 이 함수는 [배열] 의 [선언크기] 를 얻는 것이다.
  //}--------------------------------------------------------------------------------

  //[주의!!!]
  //{
      //[2007.07.23.월][추가!!!]
      //[포인터] 의 [배열] 인 경우는 실제 1 개의 요소는 무조건 8byte 가 된다.
      // "[]" 연산으로 차원이 줄어 드는 경우도 최종적으로 [포인터] 는 남게 된다.
      //즉, 이 [배열] 은 [포인터] 만의 집합체가 되는 것이다.
  //}

  //[설명]
  //{
      //[배열전체의 크기] = [type 크기] * ([1차원크기] * [2차원크기] * [3차원크기] * ... )

      //[예1]
      //{
          //[기본형] 인 경우.

          //short  ary[10][20][30];
          //short 크기------v
          //=> [ary 크기] = 2 * (10 * 20 * 30) 으로 간단하게 계산할수 있다.
      //}

      //[예2]
      //{
          //[포인터] 인 경우.

          //이 경우는 [포인터] 의 집합체가 되므로 [type크기] 는 8byte 가 된다.

          //short  **pary[10][20][30];
          //[포인터] 크기---v
          //=> [ary 크기] = 8 * (10 * 20 * 30) 으로 간단하게 계산할수 있다.
      //}

      //[예3]
      //{
          //short ary[10];

          //의 경우는 자체 type 의 크기가 된다.

          //short----v
          //[크기] = 2 * 10
      //}
  //}


  //[VAR]
  //{
      int         i;
      long long   total_size = 0;
      long long   type_size  = 0;

      //[주의!!!]
      //{
          //곱셈을 해야 하므로 1 로 초기화 해야 한다.
          long long   array_size = 1;
      //}
  //}


  //[type 크기]
  //{
      //[2007.07.23.월][수정!!!]{------------------------------------------
      //먼저 선언 type 의 [크기] 를 얻는다.
      //단, [포인터] 의 [배열] 인 경우는 모든 요소의 크기는 8byte 가 된다.
      //}------------------------------------------------------------------

      if(record[pRECindex].pointer > 0)
      {
        //[포인터]

        //[주소변수] 로 무조건 8byte 가 된다.
        type_size = 8;

      }
      else
      {
        //일반 type 크기를 얻는다.
        type_size = TYPELIST_Get_Size(record[pRECindex].typelistindex);

      }
  //}

  //[배열 자체 총 양]
  //{
      for(i = 0; i < record[pRECindex].arraydimension; i++)
      {
        //각 차원의 크기를 전부 [곱셈] 하여 일단 [배열] 의 양을 얻는다.
        array_size *= record[pRECindex].arraysize[i];

      }
  //}

  //[크기계산]
  //{
      //실제 byte 단위 전체 크기를 구한다.
      total_size = type_size * array_size;
  //}

  //[크기반환]
  //{
      (*rSIZE) = total_size;
  //}

  return;

}

void __fastcall DATABASE::SIZE_StructType(int         pRECindex,
                                          long long  *rSIZE)
{
  //[2007.07.21.토][생성!!]{-------------------------------------------------------
  //{database} 상의 [구조체 선언] record-index 를 전달받아서 해당 [구조체-type] 의
  //byte 단위 크기를 구해서 반환한다.
  //[구성원] 각각은 SIZE_Data() 함수를 사용하여 간단하게 크기를 구할수 있다.

  //[2008.11.06.목][추가!!!]
  //해당 구조체의 record 에 구해진 크기 정보를 record.size 에 기록해준다.
  //}------------------------------------------------------------------------------

  //[설명!!!]
  //{
      //[구조체] 는 [구성원] 의 모든 크기를 다 더한 것이 구하는 크기가 된다.
  //}


  //[VAR]
  //{
      int         i;
      long long   total_size = 0;
      long long   size       = 0;

  //}


  for(//[구성원] 은 "[구조체 record] + 1" 위치부터 해당된다.
      i = pRECindex + 1;
      //[구성원] 은 motheriindex 가 모체의 record-index 와 같다.
      pRECindex == record[i].motherindex;
      //[구성원] 은 {database} 에 연속적으로 배치되 있다.
      i++)
  {
    //[offset address 구하기]
    //{
        //[2008.11.05.수][추가!!!]{----------------------------------------------------
        //어차피 크기를 얻은것으로 바로 각각 [구성원] 의 [추가주소] 를 얻을수 있으므로
        //여기서 바로 [추가주소] 를 기록해 놓는다.
        //실제 [1차번역] 시에 "->", "." 연산자 번역시 [추가주소] 값을 사용해야 한다.
        //}----------------------------------------------------------------------------

        //이 위치에서 계속 더해지는 total_size 값이 바로 지금 [구성원] 의 [추가주소] 가 된다.
        record[i].address = total_size;

    //}

    //크기를 얻는다.
    SIZE_Data(i, &size);

    //크기를 계속 더한다.
    total_size += size;

    //[개별 크기 저장]
    //{
        //[2008.11.05.수][추가!!!]{--------------------------
        //어차피 크기 정보를 얻었으므로 이를 기록해 준다.
        //}-----------------------------------------------

        record[i].size = size;

    //}

  }

  //[구조체 크기 정보 기록]
  //{
      //[2008.11.06.목][추가!!!]{----------------------------------------------------
      //이미 구해진 이 [구조체 type] 의 크기 정보를 해당 record.size 에 기록해 준다.
      //}----------------------------------------------------------------------------

      record[pRECindex].size = total_size;

  //}

  //[크기반환]
  //{
      (*rSIZE) = total_size;

  //}

  return;

}

void __fastcall DATABASE::SIZE_UnionType(int         pRECindex,
                                         long long  *rSIZE)
{
  //[2007.07.21.토][생성!!]{-------------------------------------------------------
  //{database} 상의 [공용체 선언] record-index 를 전달받아서 해당 [공용체-type] 의
  //byte 단위 크기를 구해서 반환한다.
  //[구성원] 각각은 SIZE_Data() 함수를 사용하여 간단하게 크기를 구할수 있다.

  //[2008.11.06.목][추가!!!]
  //해당 공용체의 record 에 구해진 크기 정보를 record.size 에 기록해준다.
  //}------------------------------------------------------------------------------

  //[설명!!!]
  //{
      //[공용체] 는 [구성원] 의 크기중 가장 큰 값이 구하는 크기가 된다.
  //}


  //[VAR]
  //{
      int         i;
      long long   max_size = 0;
      long long   size     = 0;

  //}


  for(//[구성원] 은 "[공용체 record] + 1" 위치부터 해당된다.
      i = pRECindex + 1;
      //[구성원] 은 motheriindex 가 모체의 record-index 와 같다.
      pRECindex == record[i].motherindex;
      //[구성원] 은 {database} 에 연속적으로 배치되 있다.
      i++)
  {
    //[offset address 구하기]
    //{
        //[2008.11.05.수][추가!!!]{--------------------------------------------------
        //여기서 바로 [추가주소] 를 기록해 놓는다.
        //[공용체] 의 모든 [구성원] 의 [추가주소] 는 무조건 0 이 된다.
        //실제 [1차번역] 시에 "->", "." 연산자 번역시 [추가주소] 값을 사용해야 한다.
        //}--------------------------------------------------------------------------

        record[i].address = 0;

    //}

    //크기를 얻는다.
    SIZE_Data(i, &size);

    //[개별 크기 저장]
    //{
        //[2008.11.05.수][추가!!!]{--------------------------
        //어차피 크기 정보를 얻었으므로 이를 기록해 준다.
        //}-----------------------------------------------

        record[i].size = size;

    //}

    //[가장 큰 크기인가?]
    //{
        //[공용체] 는 가장 큰 크기가 자체 크기가 된다.
        if(max_size < size)
        {
          //최대크기로 기록한다.
          max_size = size;

        }

    //}

  }

  //[공용체 크기 정보 기록]
  //{
      //[2008.11.06.목][추가!!!]{----------------------------------------------------
      //이미 구해진 이 [구조체 type] 의 크기 정보를 해당 record.size 에 기록해 준다.
      //}----------------------------------------------------------------------------

      record[pRECindex].size = max_size;

  //}

  //[크기반환]
  //{
      //가장 큰 [구성원] 의 크기를 반환하게 된다.
      (*rSIZE) = max_size;

  //}

  return;

}

void __fastcall DATABASE::SIZE_ArrayElement(//[type] 관련 정보.
                                            long long   pTYPEsize,
                                            //[포인터] 인지 확인만 하기 위한것.
                                            int         pPOINTER,
                                            //[배열] 관련 정보.
                                            int         pDIMENSION,
                                            int         pARRAYsize[],
                                            long long  *rSIZE)
{
  //[2007.07.23.월][생성!!!]{---------------------------------------------------------------
  //현배 [배열] 의 정보를 전달 받아서 거느린 [요소] 의 byte 단위 크기를 반환한다.
  //이 함수는 [식] 이 해석되면서 "[]" 연산자를 사용하는 경우등에서  계속 [차원/크기] 정보가
  //수정되는데 이때 현재 [배열] 의 최대 [요소] 의 크기를 구하는 것이다.
  //즉, 이 함수는 단지 전달 받은 정보를 사용하여 계산만 수행하게 된다.
  //}---------------------------------------------------------------------------------------

  //[주의!!!]
  //{
      //이 함수는 [배열] 의 크기를 구하는 것이 아니라 [요소] 의 최대 크기를 구한다.
      //배열이 1차원인 경우는 자체 type 의 크기가 된다.(거느리는 원소가 없으므로...)
      //단, [포인터] 의 배열인 경우는 [type 크기] 는 무조건 8(주소크기) 가 된다.
  //}

  //[설명!!!]
  //{
      //[계산식]
      //{
          //[2차원이상인경우]
          //[배열원소크기] = [type 크기] * ([index 1 의 선언크기] * [index 2 의 선언크기] * ... * [index (dimension-1)의 크기])

          //[1차원인경우]
          //[배열원소크기] = [type 크기]
      //}

      //[예1]
      //{
          //short ary[10][20][30];
          //의 경우는

          //short----v
          //[크기] = 2 * (20 * 30)
          //이 된다.

          //즉, ary[x] 가 거느리는 원소의 총 크기가 된다.
      //}

      //[예2]
      //{
          //short *pary[10][20][30];
          //의 경우는

          //포인터---v
          //[크기] = 8 * (20 * 30)
          //이 된다.

          //즉, ary[x] 가 거느리는 원소의 총 크기가 된다.
      //}

      //[예3]
      //{
          //short ary[10];
          //의 경우는

          //short----v
          //[크기] = 2
          //이 된다.

          //ary[x] 의 원소크기는 자체 type 크기가 된다.
      //}
  //}


  //[VAR]
  //{
      int        i;

      //요소 개별적인 최소 크기.
      int        type_size = 0;

      //곱셈으로 처리되므로 1 로 초기화 해야 한다.
      long long  size = 1;
  //}

  //[type 크기 얻기]
  //{
      if(pPOINTER > 0)
      {
        //이 경우는 [포인터] 의 [배열] 이 된다.
        //[포인터] 인 경우는 무조건 8 byte 크기를 갖는다.
        type_size = 8;

      }
      else
      {
        //기본 type 으로 전달받은 값을 그대로 사용한다.
        type_size = pTYPEsize;

      }
  //}

  //[계산]
  //{
      // "배열이름[x]" 의 순수 양을 계산한다.
      //      v---2차원의 크기부터 계산에 포함된다.
      for(i = 1; i < pDIMENSION; i++)
      {
        size *= pARRAYsize[i];

      }

      //[최종크기]
      //{
          //type 크기를 곱하여 실제 byte 단위 크기를 구한다.
          //[배열] 이 1 차원인 경우는 for() 문이 처리 되지 않으나 size = 1 로 초기화 되 있으므로
          //type_size 가 곱해지면 자동적으로 자신의 type-size 를 갖게 된다.
          size = type_size * size;
      //}
  //}

  //[결과 반환]
  //{
      //계산결과 반환.
      (*rSIZE) = size;
  //}

  return;

}

void __fastcall DATABASE::SIZE_Pointer(//[type] 관련 정보.
                                       long long   pTYPEsize,
                                       //[포인터] 차원 정보.
                                       int         pPOINTER,
                                       long long  *rSIZE)
{
  //[2007.08.01.수][생성!!!]{-------------------------------
  //[포인터] 가 참조하는 대상의 크기정보를 반환한다.
  //이 함수는 일단 [포인터] 가 확실한 경우만 사용해야 한다.
  //}---------------------- --------------------------------

  //[설명!!!]
  //{
      //[포인터] 의 참조대상의 크기를 구한다.

      //[1차원 포인터]
      //{
          //참조대상이 [변수] 가 되므로 해당 type 의 크기가 구하는 값이 된다.
      //}

      //[다차원 포인터]
      //{
          //참조대상이 [포인터] 가 되므로 크기는 무조건 8 이 된다.
      //}
  //}

  if     (pPOINTER == 1)
  {
    //[1차원 포인터] 이므로 대상의 type 크기가 구하는 값이다.
    (*rSIZE) = pTYPEsize;

  }
  else if(pPOINTER > 1)
  {
    //[다차원 포인터] 이므로 무조건 주소변수크기 8 이 된다.
    (*rSIZE) = 8;

  }

  return;

}

void __fastcall DATABASE::SIZE_SYMBOL_1ST_Type(char        pSYMBOL[],
                                               int         pOrgTypeListIndex, //[2008.10.14.화][추가!!!]
                                               long long  *rSIZE)
{
  //[2007.08.15.수][생성!!!]{------------------------------------------------
  //"(type)X.X.index" 형식의 [1차번역기호] 에서 (type) 안의 typelistindex 를
  //추출하고 해당 type 의 크기를 구해서 반환한다.
  //}------------------------------------------------------------------------


  //[VAR]
  //{
      int        D_index;  //')' 문자의 위치.

      char       hexstr[OPT_1st_symbol_length] = {""};
      char       typestr[OPT_1st_symbol_length] = {""};

      long long  typelistindex;
  //}

                                                                                 
  //[() 위치 얻기]
  //{
      //')' 문자의 위치를 찾는다.
      D_index = STR_Pos(pSYMBOL, 0, ')');
  //}                                                        

  //[typelistindex 값 부분만 추출]
  //{
      //(type) 부분에서 type 부분만
      STR_SubString(pSYMBOL, 1, D_index - 1, typestr);
  //}

  //[typelistindex 값 얻기]
  //{
      //16진수 문자열 형태를 값으로 바꾼다.

      //먼저 16진수 문자열로 바꾼다.
      STR_Add_AB(hexstr, "0x", typestr);

      //문자열을 값으로 바꾼다.
      CONV_HexStr_To_LongVal(hexstr, &typelistindex);
      
  //}

  //[typelist size 얻기]
  //{
      //[2008.10.14.화][추가!!!]{----------------------------------------------------------
      //구조체/공용체의 경우는 (a)C.T.x 로 기호가 만들어 지므로(일반적인 상수 포인터가 됨)
      //정확한 크기를 알수 없다. 따라서 금일 record 에 추가한 org_typelistindex 정보를
      //사용하여 정확한 크기를 반환한다.
      //}----------------------------------------------------------------------------------

      if(pOrgTypeListIndex >= 0)
      {
        //이 경우는 구조체/공용체의 임시변수 경우로 원래 typelistindex 값으로 계산한다.
        typelistindex = pOrgTypeListIndex;

      }
      else
      {
        //해당하지 않는 경우는 이미 typelistindex 값을 위에서 얻었으므로 그냥 둔다.

      }

      //실제 크기를 얻어 값을 반환한다.
      (*rSIZE) = TYPELIST_Get_Size(typelistindex);

  //}

  return;

}


//[DEFINELIST]------------------------------------------------------------------

void __fastcall DATABASE::DEFINELIST_Format(struct DEFINEITEM *pDEFINELIST)
{
  //[2006.01.10.화][생성!!!]{-------------
  //definelist 정보 구조체를 초기화 한다.
  //}-------------------------------------

  pDEFINELIST->defname[0]    = '\0';
  pDEFINELIST->index         = -1;
  pDEFINELIST->filelistindex = -1;
  pDEFINELIST->defstr[0]     = '\0';

  return;

}

bool __fastcall DATABASE::DEFINELIST_Add(struct DEFINEITEM *pDEFINELIST)
{
  //[2005.10.17.월][생성!!!]{-------------------------------------------
  //#define 으로 정의된 [정의 문자열] 을 definelist[] 에 추가한다.
  //definelist[] 의 저장 한계를 넘지 않도록 해야 하고, 만일 저장 한계를
  //넘는 경우는 에러로 간주한다.
  //저장한 defilelist[] 상의 index 값을 반환한다.
  //}-------------------------------------------------------------------

  //[주의!!!]{------------------------------------------------------------------
  //#define 으로 선언된 [정의 문자열] 은 [name] 이 서로 달라도 같을수가 있다.
  //즉,
  //#define A 100
  //#define B 100
  //의 경우 [name] 은 A, B 로 서로 다르지만 [정의문자열] 은 100 으로 서로 같다.
  //이 경우 중복이 될수 있으므로 filelist[] 의 경우와는 달리 중복 검사는 하지
  //않는다. 그냥 맨 뒤에 추가해 주면 된다.
  //
  //이미 같은 이름이 있는지 검사하고 같은 이름이 있다면 이전 이름 위치에
  //덮어쓴다.
  //즉, 같은 이름이 있는 경우는 나중에 선언된 것을 우선한다.
  //}---------------------------------------------------------------------------

  //[2006.01.09.월][수정!!!]{--------------------------------------------------
  //#define 으로 정의된 것은 {DATABASE} 에 저장되지 않고 별도 관리 하는 것으로
  //개념 바뀌었으므로 이에 대한 수정을 하였다.
  //}--------------------------------------------------------------------------


  //[VAR]
  //{
      int  i;
      int  definelist_index = -1;
  //}


  //[저장한계 초과 검사]
  //{
      //저장 공간의 한계를 넘었는지 검사한다.
      if(definelist_count >= OPT_define_list_size)
      {
        //의미 없는 값으로 반환.
        pDEFINELIST->index = -1;

        //함수 error!!!
        return(false);

      }
  //}


  //[!]{------------------------------------------------
  //여기까지 온것은 저장 가능한 것이므로 뒤에 추가한다.
  //}---------------------------------------------------


  //[2006.05.12.금]
  //{
      //*****************************************************************************************************
      //이미 같은 이름이 있는지 검사하고 같은 이름이 있다면 이전 이름 위치에
      //덮어쓴다.
      //즉, 같은 이름이 있는 경우는 나중에 선언된 것을 우선한다.
      if(DEFINELIST_Search_withName_inAllFile(0,                          //초기 검색은 무조건 index:0 부터.
                                              pDEFINELIST->filelistindex, //검색은 현재 file 부터.
                                              pDEFINELIST->defname,       //검사할 단어.
                                              &definelist_index) == false)
      {
        //함수 error!!!
        return(false);

      }

      if(definelist_index > -1)
      {
        //이미 같은 [이름] 이 있으므로 이 위치에 [덮어쓴다].
        definelist[definelist_index] = (*pDEFINELIST);

        //이미 있는 위치에 덮어쓴 것이므로 count 하지 않는다.

      }
      else
      {
        definelist[definelist_count] = (*pDEFINELIST);

        //count 를 증가시킨다.
        definelist_count++;

      }
      //*****************************************************************************************************
  //}


  //[!]{-------------------------------------
  //여기까지 온것은 이상 없는 것이다.
  pDEFINELIST->index = (definelist_count-1);

  return(true);
  //}----------------------------------------

}

bool __fastcall DATABASE::DEFINELIST_Delete(int pDELETEindex)
{
  //[2005.10.17.월][생성!!!]{---------------------------------------------
  //definelist[] 상의 지정 index 항목을 삭제하고 빈곳을 끌어 당겨 매꾼다.
  //}---------------------------------------------------------------------

  //[2006.01.09.월][수정!!!]{-------------------------------------------------
  //#define 으로 정의된 것은 {DATABASE} 에 저장하지 않고 definelist[] 에 별도
  //저장 관리 하는 것으로 개념 수정 된것 반영한다.
  //}-------------------------------------------------------------------------


  //[VAR]
  //{
      int  i;
  //}


  //[검사]
  //{
      //[2005.10.17.월][추가!!!]
      //먼저 삭제하려는 index 값이 저장된 index 범위를 넘지 않았는지 검사한다.

      if(!((0 <= pDELETEindex) && (pDELETEindex < definelist_count)))
      {
        //이 경우는 삭제하는 index 가 범위에 맞지 않으므로 error!!!
        return(false);

      }
  //}

  //[삭제]
  //{
      //지정 위치의 정보를 삭제하는 것은 그다음의 정보를 끌어다 덮어 버리면 된다.
      for(i = pDELETEindex; i < (definelist_count - 1); i++)
      {
        //뒤의 것을 앞으로 [copy] 해서 삭제된 record 를 매꾼다.
        definelist[i] = definelist[i+1];

      }
  //}

  //[record] 가 하나 줄었으므로 record 개수를 수정한다.
  definelist_count--;

  //여기까지 온것은 아무 이상없는 것이다.
  return(true);
 
}

bool __fastcall DATABASE::DEFINELIST_Search_withName(int    pStartIndex,
                                                     char  *pName,
                                                     int   *rDefineListIndex)
{
  //[2012.04.05.목][생성!!!]{----------------------------------------------------------------
  //<#define> 은 <Parser()> 에 단어를 정의하는 것으로 간주하고 일단 어느 문서에서 선언됐든지 
  //한번 선언된 것은 이후 모든 문서에서 사용할수 있는 것으로 수정.
  //따라서, 단순하게 {DEFINELIST[]} 를 대상으로 단순하게 비교 처리.
  //
  //중복 이름의 경우는 나중것으로 덮어쓰는 형식으로 저장돼 있으므로 단순하게 찾기만 하면 된다.
  //
  //찾는 것이 없는 경우 <-1> 반환.
  //
  //[참고!!!]---------------------------------------------------------
  //[실시간 선언정보 수집] 시 보다 처리 속도를 빠르게 하기 위한것.
  //}----------------------------------------------------------------------------------------


  //[VAR]
  //{
      int  i;

  //}


  //[검사]
  //{
      //먼저 pStartIndex 가 현재까지 {definelist[]} 에 저장된 index 범위 안에 있는지 검사.
      if(!((0 <= pStartIndex) && (pStartIndex <= definelist_count)))
      {
        //지정 위치가 범위를 벗어났으므로 처리하지 않는다.
        (*rDefineListIndex) = -1;

        return(false);

      }
  //}
  

  //[같은 이름 찾기]
  //{
      //{definelist[]} 상에서 같은 이름이 있는지 검사한다.
      for(i = pStartIndex; i < definelist_count; i++)
      {
        if(STR_Match(pName, definelist[i].defname) == true)
        {
          //찾은 항목의 <index> 반환.
          (*rDefineListIndex) = i;

          return(true);

        }

      }

  //}

  //[!]{----------------------------------------------------
  //여기까지 온것은 name 이 일치하는 record 가 없는 것이다.
  (*rDefineListIndex) = -1;

  //이상 없이 검색을 바쳤으므로 true.
  return(true);
  //}-------------------------------------------------------

}

bool __fastcall DATABASE::DEFINELIST_Search_withName_inFile(int   pSTARTindex,
                                                            int   pFILELISTindex,
                                                            char *pNAME,
                                                            int  *pDEFINELISTindex)
{
  //[2006.01.10.화][생성!!!]{-------------------------------------------------------
  //definelist[] 를 뒤져서 pNAME 과 일치하는 index 를 반환한다.
  //단, 처음부터 검색하는 것이 아니고 지정된 위치 pSTARTindex 부터 검사를 시작한다.
  //반환 값 -1 : 찾는 것이 없다는 뜻.
  //definelist[] 상에서 지정된 file 에 한정해서 찾는다.
  //definelist[] 에는 filelistindex 정보가 들어 있으므로 간단하게 찾을수 있다.
  //}-------------------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  //[검사]
  //{
      //먼저 pSTARTindex 가 현재까지 definelist[] 에 저장된 index 범위 안에 있는지 검사한다.
      if(!((0 <= pSTARTindex) && (pSTARTindex <= definelist_count)))
      {
        //지정 위치가 범위를 벗어났으므로 처리하지 않는다.
        (*pDEFINELISTindex) = -1;

        return(false);

      }
  //}

  //[검사]
  //{
      //먼저 pFILELISTindex 가 현재까지 filelist[] 에 저장된 index 범위 안에 있는지 검사한다.
      //0 번 file 은 "GIGYEIN" file 로 이는 SYSTEM 예약이므로 사용해서는 안된다.
      if(!((0 < pFILELISTindex) && (pFILELISTindex < filelist_count)))
      {
        //지정 위치가 범위를 벗어났으므로 처리하지 않는다.
        (*pDEFINELISTindex) = -1;

        return(false);

      }

  //}

  //[search]
  //{
      //definelist[] 상에서 같은 이름이 있는지 검사한다.
      for(i =  pSTARTindex; i < definelist_count; i++)
      {
        //먼저 지정된 file 에 속한 record 를 찾는다.
        if(pFILELISTindex == definelist[i].filelistindex)
        {
          if(STR_Match(pNAME, definelist[i].defname) == true)
          {
            //같은 이름을 찾은 것이다. 현재 index 를 반환한다.
            (*pDEFINELISTindex) = i;

            return(true);

          }

        }

      }

  //}

  //[!]{----------------------------------------------------
  //여기까지 온것은 name 이 일치하는 record 가 없는 것이다.
  (*pDEFINELISTindex) = -1;

  //이상 없이 검색을 바쳤으므로 true.
  return(true);
  //}-------------------------------------------------------

}

bool __fastcall DATABASE::DEFINELIST_Search_withName_inAllFile(int   pSTARTindex,
                                                               int   pFILELISTindex,
                                                               char *pNAME,
                                                               int  *pDEFINELISTindex)
{
  //[2006.01.10.화][생성!!!]{----------------------------------------------------------------
  //definelist[] 에서 pNAME 과 일치하는 index 를 반환한다.
  //단, 처음부터 검색하는 것이 아니고 지정된 위치 pSTARTindex 부터 검사를 시작한다.
  //반환 값 -1 : 찾는 것이 없다는 뜻.
  //definelist[] 전체에서 지정된 file 에 한정해서 찾되, 지정된 file 에서 include 한 모든
  //file 을 다 뒤져서 검색한다. include 된 file 에서 다시 다른 file 을 include 하는 경우에도
  //전부 검색한다.
  //file 이 include 한 file 의 정보는 filelist[] 에 기록되 있다.
  //
  //지정된 file 안에서의 검색은 DEFINELIST_Search_withName_inFile() 함수를 사용한다.
  //
  //이 함수는 하부 처리부에서 자신을 다시 호출하는 "재귀호출"을 사용한다.

  //[2008.11.09.일][수정!!!]-----------------------------------------------------------------
  //include 문서를 검사할때 가장 나중에 include 된 것부터 검사하는 것으로 방법을 수정하였다.
  //이는 가장 나중에 정의된 것을 우선시 하기 위한 방법으로 다른 복잡한 절차 없이 그냥 가장
  //나중에 include 된 부터 검사하면 자동으로 가장 나중에 정의된 것이 우선시 되기 때문이다.
  //}----------------------------------------------------------------------------------------


  //[VAR]
  //{
      int definelist_index    = -1;
      int i                   =  0;
      int inc_count           =  0;
      int inc_filelistindex   = -1;

  //}


  //[지정 file 검사]
  //{
      //우선 처음 인수로 지정된 file 안에 존재하는지 검사한다.
      if(DEFINELIST_Search_withName_inFile(pSTARTindex, pFILELISTindex, pNAME, &definelist_index) == false)
      {
        (*pDEFINELISTindex) = -1;

        //함수 error!!!
        return(false);

      }

      if(definelist_index > -1)
      {
        //원하는 것을 찾은 것이다. 찾은 index 를 반환한다.
        (*pDEFINELISTindex) = definelist_index;

        return(true);

      }

  //}

  //[!]{-----------------------------------------------------------------------
  //여기까지 온것은 지정된 현재 file 에는 없는 것이므로, 이 file 이 include 한
  //file 안에 있는지 검사한다.
  //}--------------------------------------------------------------------------

  //[include-file 존재 확인]
  //{
      //이 file 에 include 한 file 의 개수를 얻는다.
      inc_count = filelist[pFILELISTindex].include_list_count;

      //현재 이 file 안에 include 된 file 이 있는지 확인한다.
      if(inc_count <= 0)
      {
        //현재 file 에도 없고, 이 file 이 include 한 file 이 없으므로 찾는것이 없다.
        (*pDEFINELISTindex) = -1;

        //이상없이 검색을 마친 것이다.
        return(true);

      }

  //}

  //[include 된 file 안에 있는가?]
  //{
      //[중요!!!]{----------------------------------------------------------------
      //include 된 file 안에 또다른 include 된 file 이 있을수 있으므로
      //여기서는 DEFINELIST_Search_withName_inFile() 함수가 아니고 지금 함수
      //DEFINELIST_Search_withName_inAllFile() 함수를 재귀호출해서 사용해야 한다.
      //모든 include 된 file 까지 완벽하게 검색하게 된다.
      //}-------------------------------------------------------------------------

      //[2008.11.09.일][수정!!!]{------------------------------------------------------------------
      //소스 안에서 여러개의 *.h 를 include 를 하는 경우는 같은 것이 선언되 있을수 있으므로
      //이 경우는 가장 나중에 include 된 *.h 안의 정의를 우선해야 한다.
      //현재 방식으로는 define 정의 를 수집시에 한개 소스 파일안에서만 중복되는 경우 가장 나중의
      //것을 덮어쓰게 되므로 동일한 정의는 한개밖에는 없게 되지만, include 한 *.h 안에 똑같은 것이
      //있는 경우는 다른 문서로 간주하여 중복시 한개로 덮어쓰지 않는다.
      //따라서, 그냥 검사를 하면 가장 나중의 정의가 아니라 가장 처음의 정의를 사용하게 된다.
      //현재의 경우는 같은 것을 찾은 경우는 무조건 찾은 것으로 간주 하기 때문이다.
      //그래서 아래와 같이 바꾼다!
      //include 된 경우는 가장 앞에서 부터 검사하지 않고 가장 나중에 include 된 문서부터 검사한다.
      //}------------------------------------------------------------------------------------------

      //바로 위에서 추출한 inc_count 정보를 사용한다.
      //현재 file 안에 include 된 file 만 대상으로 한다.

      for(i = inc_count - 1; i >= 0; i--)
      {
        //include 된 file 의 index 를 구한다.
        inc_filelistindex =  filelist[pFILELISTindex].include_list[i];

        //[검색]
        //{
            //include 된 모든 file 까지 검색한다.
            //include 된 file 의 경우는 무조건 definelist[] 처음(0) 부터 검색한다.

            if(DEFINELIST_Search_withName_inAllFile(0, inc_filelistindex, pNAME, &definelist_index) == false)
            {
              (*pDEFINELISTindex) = -1;

              return(false);

            }

            if(definelist_index > -1)
            {
              //원하는 것을 찾은 것이다.
              (*pDEFINELISTindex) = definelist_index;

              return(true);

            }

        //}

      }

      //[이전안] //위의 것을 수정하기 전의 것!
      /*
      //바로 위에서 추출한 inc_count 정보를 사용한다.
      //현재 file 안에 include 된 file 만 대상으로 한다.
      for(i = 0; i < inc_count; i++)
      {
        //include 된 file 의 index 를 구한다.
        inc_filelistindex =  filelist[pFILELISTindex].include_list[i];

        //[검색]
        //{
            //include 된 모든 file 까지 검색한다.
            //include 된 file 의 경우는 무조건 definelist[] 처음(0) 부터 검색한다.

            if(DEFINELIST_Search_withName_inAllFile(0, inc_filelistindex, pNAME, &definelist_index) == false)
            {
              (*pDEFINELISTindex) = -1;

              return(false);

            }

            if(definelist_index > -1)
            {
              //원하는 것을 찾은 것이다.
              (*pDEFINELISTindex) = definelist_index;

              return(true);

            }

        //}

      */



  //}

  //[!]{---------------------------------------------------
  //여기까지 온것은 include 된 모든 file 에도 없는 것이다.
  (*pDEFINELISTindex) = -1;

  //검색은 이상없이 마친것이다.
  return(true);
  //}------------------------------------------------------

}

bool __fastcall DATABASE::DEFINELIST_Search_withName_Total(//현재 문서 번호.
                                                           int    pFileListIndex,
                                                           char  *pName,
                                                           int   *rDefineListIndex)
{
  //[2012.04.05.목][생성!!!]{------------------------------------------------------------
  //<DEFINELIST_Search_withName_inAllFile()> 방식은 [포함관계] 를 검사하는 부분을 계속
  //반복적으로 처리하므로 시간이 많이 걸린다.
  //
  //금일, <FILELIST:includeListTotal[]> 항목을 추가하였으므로 이 정보를 참고하여 처리.
  //<FILELIST:includeListTotal[]> 에는 해당 문서를 포함하는 모든 문서번호가 정리돼 있다.
  //즉, <define>  정의이름이 유효한 모든 문서번호를 쉽게 알수 있다.
  //이 정보를 사용시 [문법] 을 준수하면서 처리속도는 기존의 3배 이상 빨라진다.
  //
  //[참고!!!]----------------------------------------------------------------------------
  //[실시간 선언정보 수집] 시 보다 처리 속도를 빠르게 하기 위한것.
  //
  //[2012.04.08.일][추가!!!]-------------------------------------------------------------
  //실제 실험결과 [정의이름] 이 많은 경우 거의 3배 정도 빨라진다.
  //대성공작으로 이로 인하여 [실시간 선언정보 수집] 은 1만줄 이상도 거의 1.5초 안에 모든
  //처리를 종료할수 있을 정도.
  //}------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i, m;

  //}

  //[문서번호 범위 검사]
  //{
      //[!]{---------------------------------------------------------------------
      //<pFileListIndex> 가 현재까지 저장된 <filelist[]> 범위 안인지 검사.
      //0 번 file 은 "GIGYEIN" file 로 이는 SYSTEM 예약이므로 사용해서는 안된다.
      //}------------------------------------------------------------------------

      if(!((0 < pFileListIndex) && (pFileListIndex < filelist_count)))
      {
        //지정 위치가 범위를 벗어났으므로 처리하지 않는다.
        (*rDefineListIndex) = -1;

        return(false);

      }

  //}

  //[같은 이름 찾기]
  //{
      //[!]{------------------------------------------------------------------------
      //<pFileListIndex> 에 등록돼 있는 문서만을 대상으로 검사하면 된다.
      //금일 새로 추가된 <FILELIST:includeListTotal[]> 안에 이 문서에 <include> 된
      //모든 문서, 이 문서 에서 다시 <include> 된 .... 모든 문서번호가 정리돼 있다.
      //
      //먼저 [이름] 을 찾는것 보다는 [같은문서번호] 를 찾는 것이 고속처리할수 있다.
      //
      //1) <pFileListIndex> 와 같은 [문서번호] 를 가진 항목중에서 [이름] 찾기.
      //   찾았다면 종료.
      //
      //2) <pFileListIndex> 에 등록된 <includeListTotal[]> [문서번호] 와 같은 항목
      //   중에서 [이름] 찾기.
      //}---------------------------------------------------------------------------

      for(i = 0; i < definelist_count; i++)
      {
        //먼저 같은 이름 찾기.
        if(STR_Match(pName, definelist[i].defname) == true)
        {
          //문서번호 유효 확인.

          if(pFileListIndex == definelist[i].filelistindex)
          {
            //찾은 항목의 <index> 반환.
            (*rDefineListIndex) = i;

            return(true);

          }
          else
          {
            //[현재 문서가 <include> 한 문서안에 존재하나?
            for(m = 0; m < filelist[pFileListIndex].includeListTotalCount; m++)
            {
              //같은 문서번호 찾기.
              if(filelist[pFileListIndex].includeListTotal[m] == definelist[i].filelistindex)
              {
                //찾은 항목의 <index> 반환.
                (*rDefineListIndex) = i;

                return(true);

              }

            }

          }

        }

      }

  //}

  //[반환]
  //{
      //여기까지 온것은 일치하는것이 없는것.
      (*rDefineListIndex) = -1;

      //이상 없이 검색을 바쳤으므로 true.
      return(true);

  //}

}

/*
bool __fastcall DATABASE::DEFINELIST_Search_withName_Total(//현재 문서 번호.
                                                           int    pFileListIndex,
                                                           char  *pName,
                                                           int   *rDefineListIndex)
{
  //[2012.04.05.목][생성!!!]{------------------------------------------------------------
  //<DEFINELIST_Search_withName_inAllFile()> 방식은 [포함관계] 를 검사하는 부분을 계속
  //반복적으로 처리하므로 시간이 많이 걸린다.
  //
  //금일, <FILELIST:includeListTotal[]> 항목을 추가하였으므로 이 정보를 참고하여 처리.
  //<FILELIST:includeListTotal[]> 에는 해당 문서를 포함하는 모든 문서번호가 정리돼 있다.
  //즉, <define>  정의이름이 유효한 모든 문서번호를 쉽게 알수 있다.
  //이 정보를 사용시 [문법] 을 준수하면서 처리속도는 기존의 3배 이상 빨라진다.
  //
  //[참고!!!]----------------------------------------------------------------------------
  //[실시간 선언정보 수집] 시 보다 처리 속도를 빠르게 하기 위한것.
  //}------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  i, m;

  //}

  //[문서번호 범위 검사]
  //{
      //[!]{---------------------------------------------------------------------
      //<pFileListIndex> 가 현재까지 저장된 <filelist[]> 범위 안인지 검사.
      //0 번 file 은 "GIGYEIN" file 로 이는 SYSTEM 예약이므로 사용해서는 안된다.
      //}------------------------------------------------------------------------

      if(!((0 < pFileListIndex) && (pFileListIndex < filelist_count)))
      {
        //지정 위치가 범위를 벗어났으므로 처리하지 않는다.
        (*rDefineListIndex) = -1;

        return(false);

      }

  //}

  //[같은 이름 찾기]
  //{
      //[!]{------------------------------------------------------------------------
      //<pFileListIndex> 에 등록돼 있는 문서만을 대상으로 검사하면 된다.
      //금일 새로 추가된 <FILELIST:includeListTotal[]> 안에 이 문서에 <include> 된
      //모든 문서, 이 문서 에서 다시 <include> 된 .... 모든 문서번호가 정리돼 있다.
      //
      //먼저 [이름] 을 찾는것 보다는 [같은문서번호] 를 찾는 것이 고속처리할수 있다.
      //
      //1) <pFileListIndex> 와 같은 [문서번호] 를 가진 항목중에서 [이름] 찾기.
      //   찾았다면 종료.
      //
      //2) <pFileListIndex> 에 등록된 <includeListTotal[]> [문서번호] 와 같은 항목
      //   중에서 [이름] 찾기.
      //}---------------------------------------------------------------------------

      //[현재문서에서 찾기]
      //{
          for(i = 0; i < definelist_count; i++)
          {
            //같은 문서번호 찾기.
            if(pFileListIndex == definelist[i].filelistindex)
            {
              //[이름] 찾기.
              if(STR_Match(pName, definelist[i].defname) == true)
              {
                //찾은 항목의 <index> 반환.
                (*rDefineListIndex) = i;

                return(true);

              }

            }

          }

          //여기까지 온것은 현재 문서에서 존재하지 않는것.
      //}

      //[현재 문서가 <include> 한 문서에서 찾기]
      //{
          //[!]{-----------------------------------------------------------
          //[현재문서] 의 <includeListTotal[]> 에 현재 문서가 <include> 한
          //[문서번호목록] 이 들어있다.
          //}--------------------------------------------------------------

          for(i = 0; i < definelist_count; i++)
          {
            for(m = 0; m < filelist[pFileListIndex].includeListTotalCount; m++)
            {
              //같은 문서번호 찾기.
              if(filelist[pFileListIndex].includeListTotal[m] == definelist[i].filelistindex)
              {
                //[이름] 찾기.
                if(STR_Match(pName, definelist[i].defname) == true)
                {
                  //찾은 항목의 <index> 반환.
                  (*rDefineListIndex) = i;

                  return(true);

                }

              }

            }

          }

      //}

  //}

  //[반환]
  //{
      //여기까지 온것은 일치하는것이 없는것.
      (*rDefineListIndex) = -1;

      //이상 없이 검색을 바쳤으므로 true.
      return(true);

  //}

}
*/

void __fastcall DATABASE::DEFINELIST_Get_StrHandle(int pDEFILELISTindex, char **pDEFstr)
{
  //[2006.05.09.화][생성!!!]{---------------------
  //definelist[].defstr[] 의 pointer 를 넘겨준다.
  //}---------------------------------------------

  //전달 받은 포인터에 직접 문자열이 있는 장소의 [address] 를 넘겨준다.
  (*pDEFstr) = definelist[pDEFILELISTindex].defstr;

  return;

}

//[USELABELLIST]----------------------------------------------------------------
bool __fastcall DATABASE::USELABELLIST_Add(struct USELABELITEM *pLABELinfo,
                                           int                 *pUSELABELLISTindex)
{
  //[2006.02.15.수][작성!!!]{---------------------------------------
  //[사용라벨] 정보를 {DATABASE} 안의 uselabellist[] 안에 저장한다.
  //}---------------------------------------------------------------

  //[2006.06.23.금][수정!!!]
  //{
      //---------------------------------------------------------------------
      //완전하게 중복되는 정보가 있으므로, 모든 정보가 같은 것이 있는 경우는
      //추가하지 않는다.
      //---------------------------------------------------------------------
  //}

  //[2006.06.24.토][수정!!!]
  //{
      //-------------------------------------------------------------
      //[사용라벨] 의 uselabellist[] 상의 저장 위치를 반환한다.
      //이는 [1차번역] 에 사용되는 symbol 을 만들기 위하여 필요하다.
      //-------------------------------------------------------------
  //}


  //[VAR]
  //{
      int  i = 0;

      //[사용라벨] 의 index 를 저장한다.(symbol 을 만들기 위한것)
      int  index = 0;
  //}


  //[record 중복 점사][2006.06.23.금][추가!!!]
  //{
      //---------------------------------------------------------------------
      //record 가 중복되는 경우는 저장하지 않는다.
      for(i = 0; i < uselabellist_count; i++)
      {
        if((STR_Match(uselabellist[i].name,(*pLABELinfo).name) == true) &&
           (uselabellist[i].filelistindex == (*pLABELinfo).filelistindex) &&
           (uselabellist[i].area == (*pLABELinfo).area))

        {
          //하나라도 같은 것이 있다면 저장하지 않는다.
          //함수 자체는 이상 없이 종료된 것이다.

          //해당 [사용라벨] 의 index 위치 저장.
          index = i;

          //이미 저장된 것이므로 다시 저장하지 않는다.
          goto USELABELINDEX;

        }
      }
      //---------------------------------------------------------------------
  //}

  //[저장한계 초과 검사]
  //{
      //-----------------------------------------------
      //저장 공간의 한계를 넘었는지 검사한다.
      if(uselabellist_count >= OPT_uselabel_list_size)
      {
        //저장공간 초과 error!!!
        return(false);

      }
      //-----------------------------------------------
  //}

  //[추가]
  //{
      //------------------------------------------------
      //해당 [사용라벨] 의 index 위치 저장.
      index = uselabellist_count;

      uselabellist[uselabellist_count] = (*pLABELinfo);
      uselabellist_count++;

      goto USELABELINDEX;
      //------------------------------------------------
  //}


  USELABELINDEX:


  //[index 정보 반환][2006.06.24.토]
  //{
      //-------------------------------
      if(pUSELABELLISTindex != NULL)
      {
        (*pUSELABELLISTindex) = index;

      }
      //-------------------------------
  //}


  return(true);

}
                     
bool __fastcall DATABASE::USELABELLIST_CheckAllDefine(//검사할 라벨이 있는 함수(영역) index.
                                                      int                   pFuncRecIndex,
                                                      //[선언라벨] 이 없는 [사용라벨] 의 정보.
                                                      struct USELABELITEM  *rEorUseLabelInfo)
{
  //[2008.11.08.토][생성!!!]{--------------------------------------------------------------------------
  //해당 함수 안에서 goto 에 [사용라벨] 이 전부 해당 함수 안에서 [선언라벨] 인지 확인한다.
  //[선언라벨] 이 없는 [사용라벨] 의 경우는 해당 정보를 반환한다(오류 정보를 표시 하기 위하여).
  //[사용라벨] 의 모든 정보는 uselabellist[] 에 모두 둘어 있다.
  //
  //[2009.05.21.목][중요수정!!!]-----------------------------------------------------------------------
  //{DATABASE} 상에는 [함수선언] 이 먼저 오고 [함수본체] 가 나중에 오는 경우는 [함수영역] 이 연속되지
  //않으므로 [라벨] 을 찾지 못하는 문제가 있다.
  //다른 곳은 이런 문제를 다 해결하였으나 금일 예제를 작성하는중 아직 [라벨] 의 경우는 이 문제를
  //수정하지 않은 것을 발견하고 수정한다.
  //
  //[라벨] 은 [함수선언] 부가 아니라 [함수본체] 와만 관계가 있으므로 [함수 본체] 부분만 검사하면 된다.
  //}--------------------------------------------------------------------------------------------------

  //[사용위치]{------------------------------------------------------------------------------
  //이 함수는 TREE_FunctionDefinition() 안에서 "}" 를 검사한뒤 해당 함수 안의 [사용라벨] 이
  //모두 선언되 있는지 확인하는데 사용된다.
  //이는 [라벨] 은 해당 [함수영역] 안에서만 유효하기 때문이다.
  //}----------------------------------------------------------------------------------------


  //[VAR]
  //{
      int     i, k;

      //[주의!!!]
      //{
          //[2008.11.08.토][추가!!!]{-----------------------------------------------------
          //반드시 초기화 해야 하며 index 는 0 부터 유효하므로 -1 로 초기화 한다.
          //초기화 하지 않는 경우는 함수안에서 아무 [사용라벨] 도 없는 경우는 초기화 되지
          //않아서 포인터 오류가 발생한다.
          //}-----------------------------------------------------------------------------

          int     startIndex = -1;

      //}

  //}


  //[사용라벨 검사 시작위치 찾기]
  //{
      //[!]{----------------------------------------------------------------------
      //지정 함수와 일치하는 uselabellist[] 상의 첫번째 [사용라벨] 위치룰 찾는다.
      //이 위치가 검사를 시작하는 첫번째 [사용라벨] 이 된다.
      //}-------------------------------------------------------------------------

      for(i = 0; i < uselabellist_count; i++)
      {
        if(uselabellist[i].area == pFuncRecIndex)
        {
          //해당 함수영역의 첫번째 [사용라벨] 위치를 찾았다.
          startIndex = i;

          //원하는 [시작위치] 를 찾았으므로 여기서 종료한다.
          break;

        }
                                          
      }

  //}

  //[[사용라벨]이 모두 [선언] 되 있는가?]
  //{
      for(i = startIndex; (uselabellist[i].area == pFuncRecIndex) && (i < uselabellist_count); i++)
      {
        //해당 함수 영역의 모든 [사용라벨] 을 검사한다.

        //[2009.05.21.목][중요수정!!!]{---------------------------------------------------------
        //[함수] 영역은 [함수선언] 이 먼저 오고 [함수본체] 가 나중에 올수 있는데 이 경우
        //[함수영역] 이 연속되지 않으며, [라벨] 은 반드시 [함수본체] 안에만 있을수 있으므로
        //이를 구분하여 [함수본체] 부분만을 대상으로 처리해 주어야 한다.
        //
        //(1) 일단 일치하는 [함수영역] 을 찾는다.
        //
        //(2) 찾은 것이 [함수선언] 부라면 [라벨] 이 사용될수 없으므로 [함수본체] 부분을 찾는다.
        //    찾은 것이 [함수본체] 하면 여기를 대상으로 검사한다.
        //
        //(3) [함수본체] 영역을 찾았다면 여기를 대상으로 검사한다.
        //
        //(4) [함수본체] 는 한번의 영역으로 끝나므로 더이상 검사하지 않는다.
        //}-------------------------------------------------------------------------------------

        //[<함수영역> 찾기]
        //{
            //먼저 [함수영역] 을 찾는다.
                                              
            for(//함수안의 record 는 함수 record + 1 의 위치부터 시작한다.
                k = pFuncRecIndex + 1;
                k < record_count;
                k++)
            {
              //[함수영역] 과 일치 하는가?
              if(record[k].area == pFuncRecIndex)
              {
                //[선언라벨] record 만을 대상으로 검사한다.

                if(record[k].kind == _recKIND_label)
                {
                  //지금 [사용라벨] 과 이름이 일치하는지 확인한다.

                  if(STR_Match(uselabellist[i].name, record[k].name) == true)
                  {
                    //일치하는 [선언라벨] 을 찾은 것이므로 추가 정보를 수집한다.

                    //[defRecIndex]{--------------------------------------------------
                    //해당 [선언라벨] 의 {DATABASE} 상의 record 위치를 기록해 놓는다.
                    //이는 ASM 번역시 보다 편리하게 정보에 접근하기 위한 것이다.
                    uselabellist[i].defRecIndex = k;
                    //}---------------------------------------------------------------

                    //계속 다름 [사용라벨] 을 검사한다.
                    goto NEXTUSELABEL;

                  }

                }

              }
              else
              {
                //[2009.05.21.목][추가!!!]{---------------------------------------------
                //해당 [함수영역] 을 벗어난 것이다.
                //이 경우는 현재 검사한 부분이 [함수선언] 에 해당하는 경우는
                //다시 [함수본체] 가 있는 영역을 찾아서 다시 검사를 시작해 주어야 한다.
                //}---------------------------------------------------------------------

                //현재 검사한것 이전의 것의 [종류] 를 구분한다.
                switch(record[k - 1].kind)
                {
                  //아래 3 경우라면 단지 [함수선언부] 만 있는 것이므로 [라벨] 이 존재할수 없다.
                  case _recKIND_func_def   :
                  case _recKIND_func_body  :
                  case _recKIND_func_param :
                  {
                    //[!]{----------------------------------------------------------------------
                    //이 경우는 현재 검사한 [영역] 은 [함수선언] 이므로 [함수본체] 가 있는 곳을
                    //찾아서 계속 검사를 해 주어야 한다.
                    //함수 내부에 별다른 [변수], [라벨] 이 없는 경우는 찾지 못할수도 있다.
                    //}-------------------------------------------------------------------------

                    //[<함수본체> 찾기]
                    //{
                        //현재 k 위치부터 다시 검사한다.
                        for( ;
                            k < record_count;
                            k++)
                        {
                          //해당 [함수영역] 인가?
                          if(record[k].area == pFuncRecIndex)
                          {
                            //[!]{------------------------------------------------------
                            //해당하는 함수 영역을 찾았으므로 다시 여기서부터 검사한다.
                            //자동으로 현재 K 위치부터 검사된다.
                            //}---------------------------------------------------------

                            goto FUNCBODY_START;

                          }

                        }

                        //[!]{--------------------------------------------------------
                        //여기까지 온것은 더이상 해당 [함수영역] 을 찾지 못한 것이다.
                        //그대로 두면 아래 [찾지 못했다] 부분에서 자동 처리된다.
                        //}-----------------------------------------------------------

                    //}

                  }

                }

              }

            }

            //[찾지 못했다]
            //{
                //여기까지 온것은 현재 [사용라벨] 은 선언되지 않는 것이라는 말이 되므로 오류다.

                //[오류정보 반환/검사종료]{-----------------
                //오류가 발생한 [사용라벨] 정보를 반환한다.
                (*rEorUseLabelInfo) = uselabellist[i];
                //더이상 검사하지 않고 바로 종료한다.
                return(false);
                //}-----------------------------------------

            //}

        //}

        FUNCBODY_START:

        //[함수본체 안에서 검사]
        //{
            //계속 이전 k 위치 부터 검사를 시작한다.
            for( ;
                //해당 함수 영역의 record 만 대상으로 한다.
                (record[k].area == pFuncRecIndex) && (k < record_count);
                k++)
            {
              //[선언라벨] record 만을 대상으로 검사한다.

              if(record[k].kind == _recKIND_label)
              {
                //지금 [사용라벨] 과 이름이 일치하는지 확인한다.

                if(STR_Match(uselabellist[i].name, record[k].name) == true)
                {
                  //일치하는 [선언라벨] 을 찾은 것이므로 추가 정보를 수집한다.

                  //[defRecIndex]{--------------------------------------------------
                  //해당 [선언라벨] 의 {DATABASE} 상의 record 위치를 기록해 놓는다.
                  //이는 ASM 번역시 보다 편리하게 정보에 접근하기 위한 것이다.
                  uselabellist[i].defRecIndex = k;
                  //}---------------------------------------------------------------

                  //계속 다름 [사용라벨] 을 검사한다.
                  goto NEXTUSELABEL;

                }

              }

            }

        //}

        //[찾지 못했다]
        //{
            //여기까지 온것은 현재 [사용라벨] 은 선언되지 않는 것이라는 말이 되므로 오류다.

            //[오류정보 반환/검사종료]{-----------------
            //오류가 발생한 [사용라벨] 정보를 반환한다.
            (*rEorUseLabelInfo) = uselabellist[i];
            //더이상 검사하지 않고 바로 종료한다.
            return(false);
            //}-----------------------------------------

        //}

        NEXTUSELABEL:

      }

      //여기까지 온것은 해당 함수 영역의 모든 [사용라벨] 은 선언된 것이다.

  //}

  return(true);

}

void __fastcall DATABASE::USELABELLIST_GetDefLabelRecindex(//[사용라벨] index.
                                                           int   pUseLabelListIndex,
                                                           //[선언라벨] 의 recindex.
                                                           int  *rDefLabelRecindex)
{
  //[2008.12.09.화][생성!!!]{-------------------------------------------------
  //[사용라벨] 의 해당 [선언라벨] 의 recindex 를 구하여 반환한다.
  //이미 모든 자료가 {uselabellist} 안에 정리되 있으므로 쉽게 처리 할수 있다.
  //}-------------------------------------------------------------------------

  (*rDefLabelRecindex) = uselabellist[pUseLabelListIndex].defRecIndex;

  return;

}

//[STRINGLIST]------------------------------------------------------------------

void __fastcall DATABASE::STRINGLIST_FirstInit(void)
{
  //[2012.04.28.토][생성!!!]{----------------------------------
  //반드시 처음 사용시 한번만 사용 초기화 할때 사용.
  //이는 [동적생성] 자를 NULL 로 처음 한번 초기화 하기 위한것.
  //}----------------------------------------------------------

  STRBUF_FirstInit(&(stringlist.strbuf));

  //[문자열] 번호는 0 부터 시작한다.
  stringlist.stringcount = 0;

  //[2009.01.07.수][추가!!!]
  stringlist.ofsAdr = 0;

  return;

}

void __fastcall DATABASE::STRINGLIST_Init(void)
{
  //[2006.06.02.금][생성!!!]

  //buffer 를 초기화 한다.
  STRBUF_Delete(&(stringlist.strbuf));

  //[문자열] 번호는 0 부터 시작한다.
  stringlist.stringcount = 0;

  //[2009.01.07.수][추가!!!]
  stringlist.ofsAdr = 0;

}

void __fastcall DATABASE::STRINGLIST_FuncInit(void)
{
  //[2008.11.11.화][생성!!!]{----------------------------------------------------------
  //TREE_FunctionDefinition() 에서 "{" 로 함수 영역이 시작되는 경우 이 함수를 사용하여
  //해당 [함수영역] 의 문자열관리정보를 초기한다.
  //이는 모든 [문자열] 은 [함수영역] 단위로 정리 관리되기 때문이다.
  //모든 C 언어는 함수 단위로 의미를 갖므으로 [라벨] 등 전부 함수단위로 관리 된다.
  //}----------------------------------------------------------------------------------

  //[문자열 저장소] 를 완전히 비운다(재생성하는 것이 아니라 내용만 없에는 것이다).
  STRBUF_Clear(&(stringlist.strbuf));

  //[문자열] 번호는 새로운 [함수영역] 에서 다시 0 부터 시작한다.
  stringlist.stringcount = 0;

  //[2009.01.07.수][추가!!!]
  stringlist.ofsAdr = 0;

}

void __fastcall DATABASE::STRINGLIST_Create(int pSIZE)
{
  //[2006.06.02.금][생성!!!]

  //stringlist 의 [문자열] 저장소 크기를 전달받아서 저장소를 생성한다.
  STRBUF_New(&(stringlist.strbuf), pSIZE);

  return;

}

void __fastcall DATABASE::STRINGLIST_Delete(void)
{
  //[2012.04.28.토][생성!!!]{--------------------------------------
  //실제는 <STRINGLIST_Init()> 함수와 같지만 <STRINGLIST_Create()>
  //함수와 대칭적인 이름을 사용하기 위하여 만든다.
  //}--------------------------------------------------------------

  STRINGLIST_Init();

}

void __fastcall DATABASE::STRINGLIST_Add(char                *pStr,
                                         int                 *rStringlistIndex,
                                         //[2009.01.07.수][수정!!!]
                                         //현 문자열의 _STR_:BASE 의 [추가주소] 를 반환한다.
                                         unsigned long long  *rStrOfsAdr)
{
  //[2006.06.02.금][생성!!!]
  //[2006.07.17.월][수정!!!]
  //{
      //---------------------------------------------------------------
      //[문자열] 을 전달 받아서 행단위로 저장해 준다.
      //이전과는 달리 [문자열라벨] 없이 [문자열] 만 행단위로 추가한다.
      //
      //"문자열0"
      //"문자열1"
      //...
      //
      //로 정리하고, 반드시 한개의 행 단위로 추가한다.
      //즉, "#STRING" 다음 행부터 stringlist-index == 0 이 된다.
      //---------------------------------------------------------------
  //}

  //[2009.01.07.수][수정!!!]{--------------------------------------------------------
  //이전과 달리 [문자열 번호] 가 아니라 전달 맏은 [문자열] 의 _STR_:BASE 로한
  //[추가주소] 를 반환해 준다.
  //이는 쉽게 구할수 있는 값으로 [1차번역] 시 부터 직접 기술하는 것이 [*.asm]
  //으로 번역시에 훨씬더 정보를 얻기 간단해 지기 때문이다.
  //[추가주소] 값은 {database}.stringlist.ofsAdr 를 참고 한다.
  //
  //[2009.05.14.목][중요수정!!!]-----------------------------------------------------
  //[제어문자] 가 있는 문자열의 경우는 이를 반영하여 실제 사용되는 정확한 길이를
  //계산하여 [추가주소] 를 계산해 주어야 한다.
  //이는 내부적으로는 [제어문자] 도 문자로 관리하지만 실제 사용시에는 해당 <code> 로
  //로 변환하여 번역해 주어야 하기 때문이다.
  //}--------------------------------------------------------------------------------

  //[VAR]
  //{
      //[2009.01.07.수][추가!!!]
      int  strLength;

  //}

  //[문자열 번호 반환]
  //{
      if(rStringlistIndex != NULL) { (*rStringlistIndex) = stringlist.stringcount; }

  //}

  //[문자열 추가]
  //{
      STRBUF_Add(&(stringlist.strbuf), "\"");

      //[문자열] 의 길이는 정해진바가 없으므로 바로 바로 추가한다.
      STRBUF_Add(&(stringlist.strbuf), pStr);

      STRBUF_Add(&(stringlist.strbuf), "\"");

      //행단위로 저장해야 하므로 행을 바꿔준다.
      STRBUF_Add(&(stringlist.strbuf), " \r\n");

      //[문자열] 을 하나 저장하였으므로 count 룰 중가 시킨다.
      stringlist.stringcount++;

  //}

  //[추가 주소 얻기]
  //{
      //현재 문자열의 [추가주소] 값은 지금 {database}.stringlist.ofsAdr 의 값이된다.
      if(rStrOfsAdr != NULL) { (*rStrOfsAdr) = stringlist.ofsAdr; }

  //}

  //[다음 문자열 추가 주소 계산]
  //{
      //[방법!!!]{------------------------------------------------------------------------
      //문자열을 끝내는 '\0' 1 Byte 포함 ----------------------------v
      //[다음 문자열 주소] = [현재 문자열 주소] + [현재문자열길이] + 1
      //
      //[2009.05.14.목][중요수정!!!]------------------------------------------------------
      //이단계의 문자열은 [제어문자] 도 아직은 단지 문자로 취급 되고 있으나
      //주소를 계산하기 위하여는 실제 [제어문자] 는 1 Byte 의 <code> 로 처리되어야 하므로
      //이를 위한 전용함수로 [제어문자] 가 반영된 정확한 실제 크기를 구한다.
      //}---------------------------------------------------------------------------------

      //현재 문자열 길이 구하기.

      //[20098.05.14.목][중요수정!!!]{-----------------------------------------
      //[제어문자] 가 반영된 정확한 크기를 구하기 위하여 전용 함수를 사용한다.
      Str_Conv_Escape(pStr, NULL, &strLength);
      //}----------------------------------------------------------------------

      //다음 문자열 [추가주소] 구하기.
      stringlist.ofsAdr += (strLength + 1);

  //}

  return;

}

void __fastcall DATABASE::STRINGLIST_TempFile_Add(void)
{
  //[2008.11.11.화][생성!!!]{----------------------------------------------
  //tempfile 의 [현재 위치] 에 수집한 [문자열] 을 추가한다.
  //[2009.01.07.수][수정!!!]
  //함수 안에서 사용된 [문자열] 을 정리하여 해당 위치에 추가하는 경우는
  //
  // FD.X.STR.{: { 문자열-ofsAdr-List }
  // "문자열..."
  // ...
  //
  //형식으로 해야 한다.
  //이 함수를 사용하는 시점에 이미 "FD.X.STR.{: " 까지는 추가된 상태이므로
  // "{ 문자열-ofsAdr-List } " 부터 나머지만 추가해주면된다.
  //}----------------------------------------------------------------------

  //[VAR]
  //{
      //[2009.01.07.수][추가!!!]
      //{
          char  ofsAdrStr[OPT_lineStrSize*4];

      //}

  //}

  //[문자열 추가 주소 목록 추가]
  //{
      //[2009.01.07.수][추가!!!]

      //[이전]{---------------------------------
      //[문자열] 의 [추가주소목록] 을 추가한다.
      //STRINGLIST_Get_OfsAdrStr(ofsAdrStr);
      //STRBUF_Add(&tempfile, ofsAdrStr);
      //STRBUF_Add(&tempfile, " \r\n");
      //[수정]----------------------------------
      STRBUF_Add(&tempfile, "\r\n");
      //}---------------------------------------

  //}

  //[정리된 문자열 추가]
  //{
      //stringlist.strbuf.buf[] 에는 현재 처리 중인 [함수영역] 안에서 사용된
      //모든 [문자열] 이 들어 있다.

      STRBUF_Add(&tempfile, stringlist.strbuf.buf);

  //}

  return;

}

bool __fastcall DATABASE::STRINGLIST_IsEmpty(void)
{
  //[2008.11.17.월][생성!!!]{-------------------------------
  //사용된 문자열이 있는지를 검사하여 해당 결과를 반환한다.
  //true  : 저장된 문자열이 하나도 없다.
  //false : 저장된 문자열이 존재한다.
  //}-------------------------------------------------------

  if(stringlist.stringcount > 0) return(false);  //저장된 문자열이 존재한다.
  else                           return(true);   //문자열이 하나도 없다.

}

int __fastcall DATABASE::STRINGLIST_StrLength(//실제는 [행번호] 이고 0 부터 시작.
                                              int  pStrIndex)
{
  //[2012.02.22.수][생성!!!]{--------------------------------------------
  //{STRINGLIST} 에 저장돼 있는 [문자열] 에서 [지정행] 에 위치한
  //[문자열] 의 순수한 길이를 반환.
  //
  //"..."[공백][CRLF]
  //"..."[공백][CRLF]
  //"..."[공백][CRLF]
  //...
  //의 형태로 각 행마다 "문자열" 로 (") 까지 전부 포함된 문자열이다.
  //
  //따라서, (") 를 제외한 사이의 문자열의 길이만 구해서 반환.
  //
  //[중요!!!]-------------------------------------------------------------
  //{STRINGLIST} 에 저장돼 있는 문자열은 아직 <CODE> 화 되있지 않은
  //[문서] 상 [문자열] 이므로 '\n', '\r' 등 [제어문자] 의 경우도 [문자열]
  //형태로 들어 있다.
  //
  //실제 <sizeof [문자열]> 의 경우는 <CODE> 화된 [문자열] 을 대상으로
  //[크기] 를 구하는 것이므로, 반드시 [제어문자] 가 반영된 <CODE> 화된
  //[문자열] 로 변환후 처리해야 한다.
  //이는 <Str_Conv_Escape()> 함수로 간단하게 처리한다.
  //
  //[참고!!!]-------------------------------------------------------------
  //이 함수는 <sizeof [식]> 을 지원하기 위한 것으로 <sizeof [문자열]> 을
  //처리하는데 필요하여 새로 만든다.
  //
  //<sizeof [문자열]> 은 [문자열길이 + 1] 을 반환해야 한다.
  //메모리 상의 차지하는 총 공간이므로 '\0' 까지 포함한 [크기] 를 반환.
  //단, 여기서는 '\0' 를 제외한 [순수한 문자열 길이] 만 반환한다.
  //
  //[사용!!!]-------------------------------------------------------------
  //<EXPRESSION_MatchOne()> 에서 <sizeof [문자열]> 처리에 사용.
  //}---------------------------------------------------------------------

  //[방법!!!]{-------------------------------------------------
  //[길이] 만 얻으면 되므로 [문자열] 자체를 얻을 필요는 없고
  //[제어문자] 가 반영된 문자열로 변환하는 <Str_Conv_Escape()>
  //함수 자체가 [길이] 만 얻는 기능이 있으므로 이 기능으로
  //[길이] 만 얻는다.
  //
  //즉, 문자열은 {STRINGLIST} 에서 1번 추출로 끝.
  //}----------------------------------------------------------

  //[VAR]
  //{
      char  lineStr[OPT_lineStrSize*10] = {""};

      int   strLength;

  //}

  //[지정 행 문자열 추출]
  //{
      //[!]{-----------------------------------------------------
      //지정 행의 문자열을 추출한다.
      //단, { "..."[공백] } 까지 추출된 상태다.
      //그러나, 이 문자열 자체를 다음의 <Str_Conv_Escape()> 에서
      //사용하는데 문제는 없다.
      //}--------------------------------------------------------

      STR_Get_LineStr_withLineNumber(stringlist.strbuf.buf,
                                     pStrIndex,
                                     lineStr);

  //}

  //[제어문자 반영/크기 얻기]
  //{
      //[!]{----------------------------------------------------------
      //<Str_Conv_Escape()> 함수로 [제어문자] 를 반영하고 동시에
      //[정리된 문자열 길이] 만 얻는다.
      //문자열 자체를 얻을필요는 없다.
      //
      //[주의!!!]-----------------------------------------------------
      //단, { "..."[공백] } 까지 추출된 문자열을 처리한 것이므로
      //["] 2 개와 [공백] 1개의 크기 <3> 을 제외한 것이 실제 구하고자
      //하는 [문자열 길이] 가 된다.
      //}-------------------------------------------------------------

      //길이는 얻기.------------------v
      //문자열은 불필요.-------v
      Str_Conv_Escape(lineStr, NULL, &strLength);

      //["] 2 개와 [공백] 1개의 크기 <3> 을 제외한 것이 실제크기.
      strLength -= 3;

      return(strLength);

  //}

}

/*
//[2009.05.14.목][페기!!!]{----------------------------------------------------
//이 함수는 문자열의 [제어문자] 를 반영하지 않고 계산하므로 실제 문제가 있으며
//사용되는 곳이 없으므로 일단 폐기한다.
//}----------------------------------------------------------------------------
void __fastcall DATABASE::STRINGLIST_Get_OfsAdrStr(char  rOfsAdrStr[])
{
  //[2009.01.05.월][생성!!!]{----------------------------------------------------------------
  //저장되 있는 [문자열] 의 _STRING_:BASE 의 [추가주소] 를 구하여 문자열로 반환한다.
  //
  // "{ ofsADR0 ofsADR1 ofsADR2 ... }"
  //
  //의 [문자열] 로 만들어 반환한다.
  //이것은 모든 [추가주소] 문자열의 기본 형식이다.
  //
  //[2009.01.08.목][수정!!!]-----------------------------------------------------------------
  //원래 이 함수의 [주소문자열] 로 각각 문자열의 주소를 계산할 것이었으나 직접
  //[문자열] 을 수집하면서 동시에 _STR_:BASE  의 [1차 추가 주소] 를 간단하게 얻을수 있으므로
  //이 방법을 사용한다.
  //즉, 이 함수 자체는 그대로 유지하고 정보도 추가하지만 참고만 하는 것으로 한다.
  //어차피 문자열 양이 많지 않아서 번역시 전혀 문제는 없다.
  //}----------------------------------------------------------------------------------------

  //[방법]
  //{
      //[1차번역] 상의 함수 안의 문자열은 이미 stringlist 정보 구조체 안에 행단위로 정리되어 있다.
      //
      // "문자열..."[공백]
      //
      //이 한개 행으로 정리되 있으므로 실제 주소는
      //[주소] = [행의길이('\0'미포함)] - 3 + 1
      //믄자열은 뒤에 '\0' 가 있어야 한다-----^
      //이 된다.
      //문자열이므로 반드시 맨 뒤에 있는 '\0'(1 byte) 까지 크기에 추가해 주어야 한다.

  //}

  //[VAR]
  //{
      int        i;

      //_STRING_:BASE 의 기본 주소는 0h 부터 시작된다.
      long long  ofsAdr    = 0;
      long long  byteCount = 0;

      char       hexStr[OPT_wordStrSize];

      int        lineCount;

  //}

  //[방법]{-------------------------------------------------------------------
  //단지 code 의 크기만 알면 되므로 처리 속도 단축을 위하여 직접 행 문자열을
  //추출하지 않고 직접 CRLF 를 검출하여 간단하게 행의 길이를 얻어서 처리한다.
  //}-------------------------------------------------------------------------

  //[초기화]
  //{
      STR_Assign(rOfsAdrStr, "{ ");

  //}

  for(//실제 행에는 ["] 다음 부터 문자열이 시작되므로 index:1 부터 시작한다.
      i = 1, ofsAdr = 0, byteCount = 0, lineCount = 0;
      lineCount < stringlist.stringcount; )
  {
    //한개 행이 끝날때 마다 이 행에대한 처리를 수행한다.

    if     ((stringlist.strbuf.buf[i] == 0x0d) && (stringlist.strbuf.buf[i + 1] == 0x0a))
    {
      //한개 행의 끝에 도달했다.

      //[byteCount 수정]
      //{
          //현재 byteCount 는 { "[공백] } 까지 포함된 것으로
          //즉, -2 를 해야 순수한 [문자열] 의 길이가 된다..
          byteCount -= 2;

      //}

      CONV_LongVal_To_Hex2(ofsAdr, hexStr);
      STR_Add(rOfsAdrStr, hexStr);
      STR_Add(rOfsAdrStr, " ");

      //[다음 주소 계산]
      //{
          //'\0' 크기 더하기-----v
          ofsAdr += (byteCount + 1);

      //}

      //[후처리]
      //{
          //현재 CR 위치에 있으므로 LF 다음에 ["] 문자 다음부터 문자가 시작되므로
          // +3 을 해야 다음 행의 시작 문자 위치가 된다.
          i += 3;

          byteCount = 0;

          lineCount++;

      //}

    }
    //
    //else if(stringlist.strbuf.buf[i] == '\0')
    //{
    //  //저장 문자열의 끝에 도달한 경우.
    //
    //  //모든 문자열을 다 처리 하였으므로 for() 를 종료한다.
    //  break;
    //
    //}
    else
    {
      i++;

      byteCount++;

    }

  }

  //[후처리]
  //{
      STR_Add(rOfsAdrStr, "}");

  //}

  return;

}
*/

//[SWITCHINFO]------------------------------------------------------------------

void __fastcall SWITCHINFO_Init(struct SWITCHINFO  *prSwitchInfo)
{
  //[2008.10.25.토][생성!!!]{-------
  //해당 정보 구조체를 초기촤 한다.
  //}-------------------------------

  prSwitchInfo->switchIndex  = 0;
  prSwitchInfo->caseCount    = 0;
  prSwitchInfo->defaultUse   = false;

  //prSwitchInfo->caseConstant[] 는 [상수값] 을 저장하므로 초기화할 필요가 없다.

  return;

}

bool __fastcall SWITCHINFO_AddCaseConstant(struct SWITCHINFO  *pSwitchInfo,
                                           long long           pCaseConstant)
{
  //[2008.10.25.토][생성!!!]{----------------
  //현재 case 위치에 해당 상수값을 저장한다.
  //}----------------------------------------

  //[용럄검사]
  //{
      if(pSwitchInfo->caseCount >= OPT_case_max) return (false);

  //}

  //사용된 상수 값을 저장한다.
  pSwitchInfo->caseConstant[pSwitchInfo->caseCount] = pCaseConstant;

  //다음 저장 위치로 이동한다(동시에 현재 case 의 개수가 된다).
  pSwitchInfo->caseCount++;

  return(true);

}

int __fastcall SWITCHINFO_MatchCaseConstant(struct SWITCHINFO  *pSwitchInfo,
                                            long long           pConstant)
{
  //[2008.10.25.토][생성!!!]{----------------------------------------
  //지정된 [상수] 와 같은 case 상수가 있다면 해당 index 를 반환한다.
  //찾는 것이 없는 경우는 -1 을 반환한다.
  //}----------------------------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  for(i = 0; i < pSwitchInfo->caseCount; i++)
  {
    if(pSwitchInfo->caseConstant[i] == pConstant)
    {
      //같은 것을 찾았다.
      return(i);

    }

  }

  //여기까지 온것은 찾는 것이 없는 것이므로 -1 을 반환한다.
  return(-1);

}

//[CTRLAREASTACK]---------------------------------------------------------------

void __fastcall CTRLAREASTACK_GetPtr(struct CTRLAREASTACK  **rCtrlAreaStackPtr)
{
  //[2008.10.27.월][생성!!!]{-----------
  //{CtrlAreaStack} 의 주소를 넘겨준다.
  //}-----------------------------------

  (*rCtrlAreaStackPtr) = &_ctrlAreaStack;

  return;

}

void __fastcall CTRLAREASTACK_Init(void)
{
  //[2008.10.27.월][생성!!!]{-----------
  //{_ctrlAreaStack} 을 초기화 한다.
  //단순하게 count 만 초기화 하면 된다.
  //}-----------------------------------

  _ctrlAreaStack.itemCount = 0;

  return;

}

bool __fastcall CTRLAREASTACK_Push(struct CTRLAREASTACKITEM  *pItem)
{
  //[2008.10.27.월][생성!!!]{---------------------------
  //{_ctrlAreaStack} 의 가장 뒤에 항목을 하나 추가한다.
  //}---------------------------------------------------

  //[범위 검사]
  //{
      //저장 용량을 초과 하지 않았는지 검사한다.
      if(_ctrlAreaStack.itemCount >= OPT_CtrlAreaStackMax) return(false);

  //}

  //[저장]
  //{
      _ctrlAreaStack.items[_ctrlAreaStack.itemCount] = (*pItem);

      //다음 저장 위치로 이동.
      _ctrlAreaStack.itemCount++;

  //}

  return(true);

}

bool __fastcall CTRLAREASTACK_Pop(struct CTRLAREASTACKITEM  *rItem)
{
  //[2008.10.27.월][생성!!!]{------------------------------------------
  //{_ctrlAreaStack} 제일 뒤에서 항목을 하나 읽어서 반환하고 삭제한다.
  //}------------------------------------------------------------------

  //[범위 검사]
  //{
      //더이상 읽을수 없는 상태인지 검사한다.
      if(_ctrlAreaStack.itemCount <= 0) return(false);

  //}

  //[읽어서 반환]
  //{
      //읽어들인 위치로 이동.
      _ctrlAreaStack.itemCount--;

      //읽어서 반환한다.
      (*rItem) = _ctrlAreaStack.items[_ctrlAreaStack.itemCount];

  //}

  return(true);

}

//------------------------------------------------------------------------------
//[PARSERINFO]------------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall DATABASE::PARSERINFO_Format(struct PARSERINFO *pPARSERINFO)
{
  //[2005.09.08.목][생성!!!]{---------------------------------
  //Parser() 함수등에서 GETNEXTWORD 구조체를 한개 생성하는데,
  //이때 이 함수로 구조체정보를 초기화 한다.
  //
  //[2012.06.22.금][추가!!!]----------------------------------
  //}---------------------------------------------------------

  //지정된 파일이 없는 상태.
  pPARSERINFO->buf           = NULL;

  pPARSERINFO->index         = 0; //(base:0)

  //아무 단어로 추출하지 않은 상태.
  pPARSERINFO->word[0]       = '\0';

  pPARSERINFO->wordindex     = 0;

  pPARSERINFO->wordLength    = 0;

  //아무 파일도 지정되지 않은 상태.
  //그러나 기본적으로 "GIGYEIN" 파일이 filelist[0] 에 위치하므로
  //이 값을 초기값으로 설정한다.
  pPARSERINFO->filelistindex = 0;

  //[2005.10.07.금][추가!!!]
  //파일의 크기 정보를 담는다. 처음에는 무조건 0 이다.
  pPARSERINFO->filesize = 0;

  //[2005.09.22.목][추가!!!]{--------------------------------
  //행정보를 저장하는 변수를 초기화 한다. 0 행부터 시작한다.
  pPARSERINFO->line = 0;
  //}--------------------------------------------------------

  //[2005.09.24.토][추가!!!]{------------------------
  //처음에는 아무 영역도 아닌 것이다.
  //GetNextWord() 함수에서 사용하는 중요한 정보이다.
  pPARSERINFO->what_in = 0;
  //}------------------------------------------------

  //[2005.10.31.월][추가!!!]{----------------------------------------
  //영역정보는 항상 처음에 -1 로 global 영역으로 설정해 놓아야 한다.
  pPARSERINFO->area_gl = -1;
  //}----------------------------------------------------------------

  //[2006.02.14.화][추가!!!]{-------------------------------------------
  //break, continue, case 등의 사용이 적당한 영역인지 확인하기 위한 것.
  //처음에는 아무 것도 오지 않았으므로 0 으로 초기화 해야 한다.
  pPARSERINFO->ctrlarea.for_count     = 0;
  pPARSERINFO->ctrlarea.while_count   = 0;
  pPARSERINFO->ctrlarea.dowhile_count = 0;
  pPARSERINFO->ctrlarea.switch_count  = 0;

  //[2009.12.08.화][추가!!!]
  pPARSERINFO->ctrlarea.return_count  = 0;
  //}-------------------------------------------------------------------

  //[2008.10.25.토]
  //{
      pPARSERINFO->ctrlarea.countIf      = 0;
      pPARSERINFO->ctrlarea.countFor     = 0;
      pPARSERINFO->ctrlarea.countWhile   = 0;
      pPARSERINFO->ctrlarea.countDowhile = 0;
      pPARSERINFO->ctrlarea.countSwitch  = 0;

  //}

  //[2006.05.09.화][추가!!!]{-------------
  pPARSERINFO->definecall_count      = 0;
  pPARSERINFO->parserinfostack_count = 0;
  //}-------------------------------------

  //[2006.06.12.월][추가!!!]
  //{
      pPARSERINFO->wordcount = 0;

  //}

  //[2012.06.22.금][추가!!!]
  pPARSERINFO->isName = false;

  //[지정 위치 정보]
  //{
      //[2012.06.23.토][추가!!!]
      pPARSERINFO->setIndex  = -1;
      pPARSERINFO->setWhatIn = 0;

  //}

}

void __fastcall DATABASE::PARSERINFO_Backup(struct PARSERINFO *pBACKUPinfo,
                                            struct PARSERINFO *pPARSERinfo)
{
  //[2006.05.09.화][생성!!!]{--------------------------------------
  //parserinfo 정보를 backup 하면서 추가 처리도 같이 수행한다.
  //{DATABASE} 안의 definecall_count, parserinfostack_count 정보를
  //현재 parserinfo 안의 해당 정보에 일단 할당후 parserinfo 전체를
  //backup 한다.
  //}--------------------------------------------------------------

  //[부가정보 backup]{------------------------------------------
  //일단 현재 parserinfo 정보에 부가 정보의 현재 값을 할당한다.
  pPARSERinfo->definecall_count      = definecall_count;
  pPARSERinfo->parserinfostack_count = parserinfostack_count;
  //}-----------------------------------------------------------

  //[backup]{---------------------------
  //현재 parserinfo 정보를 backup 한다.
  (*pBACKUPinfo) = (*pPARSERinfo);
  //}-----------------------------------

  return;

}

void __fastcall DATABASE::PARSERINFO_Restore(struct PARSERINFO *pBACKUPinfo,
                                             struct PARSERINFO *pPARSERinfo)
{
  //[2006.05.09.화][생성!!!]{--------------------------------------
  //parserinfo 정보를 restore 하면서 추가 처리도 같이 수행한다.
  //{DATABASE} 안의 definecall_count, parserinfostack_count 정보에
  //현재 restore 된 parserinfo 안의 해당 정보를 다시 복원해 준다.
  //}--------------------------------------------------------------

  //[restore]{----------------------------------------------------------
  //backup 했던 parserinfo 정보를 현재 parserinfo 로 다시 restore 한다.
  (*pPARSERinfo) = (*pBACKUPinfo);
  //}-------------------------------------------------------------------

  //[부가정보 복구]{-------------------------------------------------------
  //부가 정보를 restore 한 parserinfo 안의 해당 정보 값으로 다시 복구한다.
  definecall_count      = pPARSERinfo->definecall_count;
  parserinfostack_count = pPARSERinfo->parserinfostack_count;
  //}----------------------------------------------------------------------

  return;

}

bool __fastcall DATABASE::PARSERINFOSTACK_Push(struct PARSERINFO *pPARSERINFO)
{
  //[2005.09.12.월][생성!!!]{---------------------------------------------------
  //parserinfostack[] 에 현재의 정보를 push 한다.
  //이는 새로운 파일을 여는 경우 [현재파일의 이름] 과 [현재파일의 어디까지 처리
  //되었는가] 에 대한 정보를 push 하는 것으로, 나중에 새로 연 파일의 처리 후에
  //다시 현재 파일로 되돌아와 처리할때 필요하다.
  //모든 정보는 동일하지만 [파일버퍼] 의 경우는 다시 파일을 열때 새롭게 재 설정
  //되므로 이 것만큼은 새로 설정이 되어야 한다.(별도 처리 과정이 있어야 한다.)
  //이는 [파일열기] 함수에서 자동으로 처리되어야 한다.
  //}---------------------------------------------------------------------------

  //[검사]
  //{
      //처리 용량을 넘겼는지 확인한다.
      if(parserinfostack_count >= OPT_parserinfostack_size)
      {
        //이미 stack 이 꽉찬 것이므로 더이상 추가할수 없다.
        return(false);

      }
  //}

  //[push]
  //{
      //stack 의 가장 뒤에 전달받은 정보를 추가한다.
      //현재의 parserinfostack_count 값이 지금 저장할 index 가 된다.
      parserinfostack[parserinfostack_count]  = (*pPARSERINFO);

      //정보를 하나 추가했으므로 count 를 증가 시킨다.
      parserinfostack_count++;
  //}

  //여기까지 온것은 이상없이 잘 처리된 것이다.
  return(true);

}

bool __fastcall DATABASE::PARSERINFOSTACK_Pop(struct PARSERINFO *pPARSERINFO)
{
  //[2005.09.12.월][생성!!!]{---------------------------
  //parserinfostack[] 에 push 한 정보를 다시 꺼내 준다.
  //가장 마지막에 추가한 정보를 반환하게 된다.
  //}---------------------------------------------------

  //[검사]
  //{
      //추가된 정보가 하나도 없을수도 있으므로 이 경우를 검사한다.
      if(parserinfostack_count == 0)
      {
        //stack[] 안에 아무 것도 없으므로 꺼낼수 없다.
        return(false);

      }
  //}

  //[pop]
  //{
      //꺼낼 위치는 parserinfostack_count-1 의 index 이다.
      (*pPARSERINFO) = parserinfostack[parserinfostack_count-1];

      //한개 정보를 꺼냈으므로 count 를 감소 시켜야 한다.
      parserinfostack_count--;
  //}

  //이상없이 추출한 것이다.
  return(true);

}

void __fastcall DATABASE::FILEINFO_FirstInit(struct FILEINFO *pFileInfo)
{
  //[2012.04.27.금][생성!!!]{-------------------------------------------
  //{DB} 시작시 처음 한번만 초기화 한다.
  //[동적생성] 되는 개체를 반드시 처음 한번 NULL 로 초기화 하기 위한것.
  //}-------------------------------------------------------------------

  //반드시 NULL 로 초기화.
  pFileInfo->buf     = NULL;

  pFileInfo->handle  = NULL;
  pFileInfo->name[0] = '\0';
  pFileInfo->size    = 0;

}

void __fastcall DATABASE::FILEINFO_Delete(struct FILEINFO *pFileInfo)
{
  //[2012.04.27.금][생성!!!]{---------------------------
  //<{DB}.Delete()> 시에 같이 호출되어 삭제되어야 한다.
  //}---------------------------------------------------

  //[삭제]
  //{
      if(pFileInfo->buf != NULL) { delete [] pFileInfo->buf; }

  //}

  //반드시 NULL 로 초기화.
  pFileInfo->buf     = NULL;

  pFileInfo->handle  = NULL;
  pFileInfo->name[0] = '\0';
  pFileInfo->size    = 0;

}

void __fastcall DATABASE::FILEINFO_Format(struct FILEINFO *pFILEINFO)
{
  //[2005.09.11.일][생성!!!]{----------------------------------------------------
  //FILEINFO 구조체를 초기화 한다.
  //
  //[2009.02.07.토][중요 수정!!!]------------------------------------------------
  //[Build] 시에 {DATABASE}.Init() 에서 이 함수를 호출하게 되는데
  //이미 [Build] 처리 중에 pFILEINFO->buf 에 동적으로 생성된 공간이 있을수 있다.
  //따라서, 반드시 NULL 이 아닌 경우는 동적으로 삭제해 주어야 한다.
  //}----------------------------------------------------------------------------

  //[초기화]
  //{
      //[2009.02.07.토][수정!!!]
      //{
          //동적으로 생성된 것이 있을 경우는 동적으로 삭제해 주어야 한다.
          if(pFILEINFO->buf != NULL) { delete [] pFILEINFO->buf; }

          //초기화 한다.
          pFILEINFO->buf = NULL;

      //}

      pFILEINFO->handle  = NULL;
      pFILEINFO->name[0] = '\0';
      pFILEINFO->size    = 0;

  //}

}

//[ERRORINFO]-------------------------------------------------------------------

void __fastcall DATABASE::ERRORINFO_Init(void)
{
  //[2006.04.15.금][생성!!!]{------------
  //errorinfo 구조체 정보를 초기화 한다.
  //}------------------------------------

  //[삭제]
  //{
      //[2012.04.27.금][추가!!!]{---------------------------------------
      //기존에 생성된 것이 있다면 [삭제] 한다.
      //{DB} 시작시 한번 <STRBUF_FirstInit()> 로 초기화 했기 때문에
      //처음에는 항상 NULL 로 시작하므로 안전하게 사용할수 있다.
      //
      //여기서 계속 <STRBUF_New()> 로 [생성] 만 했는데 이 함수는
      //내부적으로 [삭제] 하지 않기 때문에 오늘 이를 발견하고 추가한다.
      //}---------------------------------------------------------------

      STRBUF_Delete(&(errorinfo.strbuf));

  //}

  //[line]----------------------------------------------------------------------------
  //에러 행은 처음에는 없는 것으로 해야 한다.
  errorinfo.line = -1;
  //[new]-----------------------------------------------------------------------------
  //STRBUF.buf[] 를 생성한다.
  //error 문자열을 전부 저장해야 하므로 일단 일단 100 KByte 정도로 넉넉하게 설정한다.
  STRBUF_New(&errorinfo.strbuf, OPT_errorviewbuf_size);
  //[word][2006.05.02.화][추가!!!]----------------------------------------------------
  errorinfo.word[0] = '\0';
  //----------------------------------------------------------------------------------

  //[2009.02.18.수][추가!!!]
  //{
      errorinfo.fileFullName[0] = '\0';

  //}

}

void __fastcall DATABASE::ERRORINFO_Line(int pERRORline)
{
  //[2006.05.01.월][생성!!!]{-----------------------------
  //이전에 직접 입력하던 값을 함수로 대체 할수 있게 한다.
  //}-----------------------------------------------------

  errorinfo.line = pERRORline;

  return;

}

void __fastcall DATABASE::ERRORINFO_Add(char *pSTR)
{
  //[2006.05.01.월][생성!!!]{--------------------
  //error 가 발생한 경우 해당 문자열을 기록한다.
  //}--------------------------------------------

  STRBUF_Add(&errorinfo.strbuf, pSTR);

  return;

}

void __fastcall DATABASE::ERRORINFO_Word(char *pERRORword)
{
  //[2006.05.02.화][생성!!!]{----------------------------------------------
  //error 가 난 [단어] 를 저장한다.
  //이 함수는 계속 사용할수 있으나, 가장 처음에 저장한 [단어] 만 유효하다.
  //즉, 이미 단어가 저장되 있다면 다시 저장해서는 안된다.
  //}----------------------------------------------------------------------

  //이미 저장된 단어가 있다면 저장하지 않는다.
  if(errorinfo.word[0] == '\0')
  {
    //error 가 난 단어를 저장한다.
    STR_Assign(errorinfo.word, pERRORword);

    //[2009.02.18.수][추가!!!]
    //{
        //[오류] 가 있는 [문서경로] 를 저장한다.
        STR_Assign(errorinfo.fileFullName, filelist[parserinfo.filelistindex].name);

    //}

  }

  return;

}

//------------------------------------------------------------------------------

bool __fastcall DATABASE::IS_Name(struct PARSERINFO *pPARSERinfo,
                                  //검사할 [이름].
                                  char              *pWORD,
                                  //true  : 겹친다.
                                  //false : 겹치지 않는다.
                                  bool              *pBOOL)
{
  //[2005.08.28.일][생성!!!!]{---------------------------------
  //{DATABASE} 를 전부 뒤져서 [name] 에 해당하는지 확인한다.
  //[name] 은 현재까지 전혀 사용되지 않은 [단어] 이어야 한다.
  //그러므로, 다른 모든 것과 겹치지 않는다면 [name] 으로 본다.
  //}----------------------------------------------------------

  //[방법]{---------------------------------------------------------------------
  //가장먼저 [name 규칙] 에 맞는지를 검사한다. 이렇게 하는 이유는 record 상에는
  //[단어] 말고 다른 정보도 [name_field] 에 저장되기 때문이고, [연산자], [기호],
  //[escape] 등을 따져 주지 않아도 되므로 처리 시간을 절약할수 있다.
  //즉, [name 규칙] 에 맞지도 않는다면 더이상 따질 것도 없다.
  //이 함수는 오직 사용할수 있는 [name] 인지 아닌지만 따지므로.
  //다음 {DATABASE} 상의 [name] 과 겹치는 것이 없는지 검사하고(record 가 대상),
  //다음 역시 단어로 구성된 [예약어] 와 일치하는 것이 없다면 사용할수 있는
  //[name] 으로 볼수 있다.
  //}---------------------------------------------------------------------------

  //[2005.10.14.금][수정!!!][중요!!!]{-------------------------------------
  //이 함수는 #include 가 지원 됨에 따라서 *.c 에 포함된 include 된 정보를
  //{DATABASE} 상에서 찾아서 name 인지를 가려야 하므로 수정되어야 한다.
  //name 인지의 검사는 *.c 안의 영역을 대상으로 한다.
  //[2005.11.03.목][추가!!!]
  //또한, local 영역이 다른 경우는 같은 [name] 을 사용할수 있으며,
  //같은 local 안에서만 겹치지 않으면 되는 규칙도 적용한다.
  //}----------------------------------------------------------------------

  //[2006.01.11.수][중요문법][수정!!!]{------------------------------------------
  //[구조체/공용체] - [member] 의 [name] 에는 [global-name] 을 사용할수 있다.
  //현재 이것이 반영되 있지 않으므로 이 규칙이 적용되도록 수정한다.
  //이 경우 현재 검사하는 name 이 [구조체/공용체 type] 안이라면 global-name 과
  //겹쳐도 무시해버리면 간단하다.
  //즉, 현재 검사하는 name 이 member 인지아닌지만 알면 된다.
  //parserinfo.area_gl 안에 영역정보 record 번호가 들어 있으므로 이를 활용한다.
  //}----------------------------------------------------------------------------


  //[VAR]
  //{
      int  i           = 0;
      int  rec_index   = 0;
      int  start_index = 0;
      int  temp        = 0;

      //[2006.01.11.수][추가!!!]
      //현재 검사하는 name 이 위치하는 area 정보가 있는 record 의 종류를 저장.
      int  now_rec_kind    = 0;
  //}


  //[name 규칙에 맞는가?]
  //{
      //가장먼저 [name 규칙] 에 맞는지 확인한다.
      //[name 규칙] 에 맞지도 않는다면 다음은 따질 것도 없다.
      //이는 처리 시간을 최소한으로 줄이기 위하여 가장 먼저 검사하는 것이다.

      if(CHECK_NameRule(pWORD) != true)
      {
        //[name 규칙] 에 조차 맞지 않으므로 사용할수 있는 [name] 이 아니다.
        (*pBOOL) = false;

        //함수자체는 이상없음!!!
        return(true);

      }
  //}

  //[keyword 와 겹치는가?]
  //{
      //[예약어] 와 겹치는 것은 없는지 확인한다.
      //기본 type 은 모두 keyword 에 포함되고, 사용자가 선언한 [구조체/공용체 type]
      //이름은 {DATABASE} 상에 모두 존재 하므로 typelist[] 안의 것과 별도로 비교 검사
      //할 필요는 없다.

      if(IS_Keyword(pWORD) == true)
      {
        //[예약어] 와 겹치므로 사용가능한 [name] 이 아니다.

        (*pBOOL) = false;

        return(true);

      }
  //}

  //[{DATABASE} 에서 name 이 중복되는가?]
  //{
      //[대폭수정!!!]{---------------------------------------------------------------------------
      //#include 로 추가된 file 안의 정보와도 겹치는지 전부 검사해야 하고(유효 영역만 검사)
      //서로 다른 함수 안에서는 같은 name 이 있어도 되므로 함수이름(local area) 도 모두 검색해서
      //사용가능한지 여부를 검사해 주어야 한다.
      //}----------------------------------------------------------------------------------------

      //[2005.11.03.목][검사방법!!!]{------------------------------------------------------
      //아래의 두개 조건을 만족 시키면 된다.
      //[1] : global name 과 겹치는 것이 없어야 한다.
      //[2] : [1] 의 조건을 만족 시키는 경우에만 성립되고,
      //      현재 검사하고자 하는 word 의 local-area 안에서 겹치는 것이 없어야 한다.
      //      local-area 는 [함수] 뿐만 아니라 [구조체/공용체 type] 안의 영역도 포함되며,
      //      오로지 현재 검사하고자 하는 단어가 있는 local-area 만 대상으로 하면 된다.
      //
      //위의 모든 검사는 REC_Search_withName_inAllFile() 함수로 처리하되, global 의 경우는
      //{DATABASE} 의 처음 index 부터, local-area 를 대상으로 하는 경우는 현재 loacl-area
      //선언정보가 있는 index 위치부터 지정하여 검사하면 된다.
      //}----------------------------------------------------------------------------------

      //[global 과 겹치는가?]
      //{
          //[!]{-----------------------------------------------------------------------------------------
          //현재 영역이 global, local 인지에 상관 없이 무조건 global 에 선언된 것들과는 겹쳐서는 안된다.
          //단, 현재 검사하는 단어가 [구조체/공용체 member] 가 아닐 경우.
          //
          //[2006.01.11.수][수정!!!]{--------------------------------------------------------------------
          //현재 검사하는 단어가 [구조체/공용체 type] 안에 있는 member 라면 global 과 겹치는 것은
          //완전히 무시해도 된다.
          //}--------------------------------------------------------------------------------------------
                  
          //[현재 name 이 member 인가?]
          //{
              //[!]{----------------------------------------------------------------------------------
              //parserinfo.area_gl 정보를 사용하여 현재 단어가 위치하는 영역의 record 종류가
              //[구조체/공용체 type] 인지 확인한다. 이는 현재 검사하는 단어가 member 가 되는지
              //확인하기 위한 것이다.
              //
              //[주의!!!]-----------------------------------------------------------------------------
              //기본적으로 현재 단어가 global 영역이라면 member 일리가 없으므로 아예 검사하지 않는다.
              //이는 비교 검사시 처리 시간을 줄이는데 목적이 있다.
              //}-------------------------------------------------------------------------------------

              if(pPARSERinfo->area_gl > -1)
              {
                //[!]{--------------------------------------------------------------
                //이 경우는 [함수영역(local)] 이던지 [구조체/공용체] 안인 경우이다.
                //area_gl == -1 인 경우는 global 영역이기 때문이다.
                //}-----------------------------------------------------------------

                //[kind 추출!!!]
                if(REC_Field_Read2(pPARSERinfo->area_gl, _F_kind, NULL, &now_rec_kind) == false)
                {
                  //함수 처리 에러!!!
                  (*pBOOL) = false;

                  return(false);

                }

                //현재 검사하는 단어가 위치한 [영역 종류] 를 검사한다.
                if((now_rec_kind == _recKIND_structtype) || (now_rec_kind == _recKIND_uniontype))
                {
                  //[!]{-------------------------------------------------------------------
                  //현재 [구조체/공용체 type] 선언 영역이므로 지금 name 은 member 가 된다.
                  //그러므로 global 영역의 이름과 겹칠수 있으므로 global 과 비교하는 것은
                  //검사하지 않는다.
                  //}----------------------------------------------------------------------

                  //[PASS!!!]
                  //{
                      //global 과 겹치는지 검사하지 않고 바로 다음단계로 넘어간다.
                      goto GLOBAL_CHECK_PASS;

                  //}

                }

              }

          //}

          //[gloabl 과 겹치는가!!!]
          //{
              //현재 단어가 global 과 겹치는지 확인!!!
              if(REC_Search_withArea_Name_inAllFile(start_index,
                                                    pPARSERinfo->filelistindex, //현재 처리 중인 파일.
                                                    -1,                         //영역은 global 로 설정하여 검색한다.
                                                    pWORD,                      //검사할 단어.
                                                    &rec_index) == false)
              {
                //함수 처리 에러!!!
                (*pBOOL) = false;

                return(false);

              }

              //겹치는 것이 있는지 확인한다.
              if(rec_index > -1)
              {
                //global 과 겹치는 것이 있으므로 사용할수 없는 name 이다.
                (*pBOOL) = false;

                return(true);

              }

          //}

      //}


      GLOBAL_CHECK_PASS:


      //[!]{-----------------------------------------------
      //여기까지 온것은 global 과 겹치는 것이 없는 것이다.
	  //이제, global/local 영역에 따른 처리를 수행한다.
      //}--------------------------------------------------

      if(pPARSERinfo->area_gl == -1)
      {
        //[현재 global 영역인 경우]

        //이미 global 에 선언된 것들과 겹치는 것이 없으므로 사용할수 있는 이름이다.
        (*pBOOL) = true;

        return(true);

      }
      else
      {
        //[현재 local 영역인 경우]

        //[참고!!!]{--------------------------------------------------------------------
        //local-area 를 검색할때는 parserinfo.area_gl 값이 해당 영역의 {DATABASE} 상의
        //시작 record-index 값이 되므로 local-area 는 이 위치부터 검색을 시작해야 한다.
        start_index = pPARSERinfo->area_gl;
        //}-----------------------------------------------------------------------------

        //현재 local 영역안에서 겹치는 것이 있는지 검사한다.
        if(REC_Search_withArea_Name_inAllFile(start_index,
                                              pPARSERinfo->filelistindex, //현재 처리중인 파일.
                                              pPARSERinfo->area_gl,       //현재 영역 정보로 검색.
                                              pWORD,
                                              &rec_index) == false)
        {
          //함수 처리 에러!!!
          (*pBOOL) = false;

          return(false);

        }

        //겹치는 것이 있는지 확인한다.
        if(rec_index > -1)
        {
          //현재 local 영역에서 겹치는 것이 있으므로 사용할수 없는 name 이다.
          (*pBOOL) = false;

          return(true);

        }

      }
  //}
                                                       
  //[!]{-----------------------------------------------
  //여기까지 온것은 겹치는 것이 아무것도 없는 것이므로
  //사용할수 있는 [name] 으로 본다.
  (*pBOOL) = true;
  return(true);
  //}--------------------------------------------------

}

bool __fastcall DATABASE::Is_FunctionName(struct PARSERINFO *pParserInfo,
                                          //검색할 단어.
                                          char              *pWord,
                                          //찾았는지(true) 못찾았는지(false) 를 구분.
                                          bool              *rBool,
                                          //찾은 위치.
                                          int               *rFuncRecIndex)
{
  //[2006.01.19.목][생성!!!!]{-------------------------------------------------------------
  //{DATABASE} 를 전부 뒤져서 전달받은 pWord 가 [함수이름] 인지
  //확인하고, [함수이름] 이라면 {DATABASE} 상의 record-index 를 반환한다.
  //
  //[2009.03.26.목][중요수정!!!]-----------------------------------------------------------
  //[함수이름] 의 경우는 [설계묶음] 단위 작업으로 [설계묶음] 상에서 절대
  //겹칠수 없으므로 전체 {DATABASE} 를 대상으로 검사해야 한다.
  //그렇지 않는 경우는 서로다른 문서에 함수가 기술된 경우 중복등록된다.
  //즉, "A.c" 에는 함수본체를 기술하고 "B.c" 에서 "A.h" 를 <include> 하여 사용하는경우
  //이전과 같이 [문서] 단위 검색을 하는 경우는 "B.c" 문서에는 함수가 존재하지만
  //"A.c" 문서에는 자신밖에 없으므로 결국 중복되는 것이 없는 것으로 되어
  //"A.c" 안의 함수가 중복 등록되게 된다.
  //금일 이런 문제를 발견하고 무조건 전체 {DATABASE} 를 대상으로 검사하는 것으로 수정한다.
  //}--------------------------------------------------------------------------------------

  //[방법!!!]{------------------------------------------------------------------------
  //(1) 일단 현재까지의 모든 {DATABASE} 의 전역 영역을 대상으로 검색한다.
  //    함수 선언이라면 당연히 <area: -1> 이므로 [전역영역] 만 검사하면 된다.
  //
  //(2) 해당 <record-kind> 가 <_recKIND_func_def> 나 <_recKIND_func_body> 중 하나라면
  //    함수 <record> 로 보고 원하는 것을 찾은 것이다.
  //}---------------------------------------------------------------------------------

  //[VAR]
  //{
      int  rec_index   = 0;
      int  rec_kind    = 0;

  //}

  //[초기화!!!]{--------------------------
  //일단 반환 값을 초기화 해준다.
  if(rBool != NULL) { (*rBool) = false; }
  (*rFuncRecIndex) = -1;
  //}-------------------------------------

  //[이름 규칙에 맞는가?]
  //{
      //[!]{-----------------------------------------------------------------
      //가장먼저 [이름 규칙] 에 맞는지 확인한다.
      //[이름 규칙] 에 맞지도 않는다면 다음은 따질 것도 없다.
      //이는 처리 시간을 최소한으로 줄이기 위하여 가장 먼저 검사하는 것이다.
      //}--------------------------------------------------------------------

      if(CHECK_NameRule(pWord) != true)
      {
        //[이름 규칙] 에 조차 맞지 않으므로 사용할수 있는 [이름] 이 아니다.

        //함수자체는 이상없음!!!
        return(true);

      }

  //}

  //[예약어 와 겹치는가?]
  //{
      //[!]{-------------------------------------------------------------------------------------
      //[예약어] 와 겹치는 것은 없는지 확인한다.
      //기본 <type> 은 모두 <예약어> 에 포함되고 사용자가 선언한 [구조체/공용체 type 이름] 은
      //{DATABASE} 상에 모두 존재 하므로 <typelist[]> 안의 것과 별도로 비교 검사 할 필요는 없다.
      //}----------------------------------------------------------------------------------------

      if(IS_Keyword(pWord) == true)
      {
        //[예약어] 와 겹치므로 사용가능한 [이름] 이 아니다.

        //함수자체는 이상없음!!!
        return(true);

      }

  //}

  //[함수이름 인가?]
  //{
      //[이름 이 같은 것 찾기]
      //{
          //[함수선언] 은 global 영역만 가능하므로 global 영역에서만 검사한다.

          if(REC_Search_withNameAndArea(//[설계묶음] 전체를 대상으로 하므로 {DATABASE} 처음부터 검색한다.
                                        0,
                                        pWord,
                                        //[함수이름] 만 찾을 것이므로 [전역영역] 만 대상으로 한다.
                                        -1,
                                        //전체를 대상으로 검색한다.
                                        true,
                                        &rec_index) == false)
          {
            //함수 처리 에러!!!
            return(false);

          }

      //}

      //[같은것 찾기]
      //{
          //겹치는 것이 있는지 확인한다.
          if(rec_index > -1)
          {
            //<record-kind> 를 구하기.
            if(REC_Field_Read2(rec_index, _F_kind, NULL, &rec_kind) != true) { return(false); }

            //<_recKIND_func_def>, <_recKIND_func_body> 라면 [함수 record] 이다.
            if((rec_kind == _recKIND_func_def) || (rec_kind == _recKIND_func_body))
            {
              //현재 단어는 [함수이름] 이다.
              if(rBool != NULL) { (*rBool) = true; }

              //해당 함수의 rec-index 를 반환한다.
              (*rFuncRecIndex) = rec_index;

              //이상없이 처리된 것이다.
              return(true);

            }

          }

      //}

  //}

  //[!]{-------------------------------------------------
  //여기까지 온것은 pWord 는 [함수이름] 이 아닌 것이다.
  //함수는 이상없이 처리된 것이다.
  //}----------------------------------------------------

  return(true);

}

bool __fastcall DATABASE::Is_LocalVar(struct PARSERINFO *pParserInfo,
                                      char              *pWord,
                                      int                pArea,
                                      int               *rVarRecIndex)
{
  //[2009.03.27.금][생성!!!!]{-------------------------------------------------------------
  //{DATABASE} 를 전부 뒤져서 [순수한 지역변수] 중에서 해당하는 것을 검색한다.
  //[설계묶음] 단위로 작업하므로 전체를 다 검색해야 한다(특정 문서만 대상으로하지 않는다).
  //단, [구조체/공용체] 의 [구성원] 인 경우는 안되며 순수한 [지역변수] 인 경우만 해당한다.
  //이는 현재 [영역] 이 [함수 영역] 인 경우인지만 확인하면 간단하게 구분할수 있다.
  //}--------------------------------------------------------------------------------------

  //[방법]{------------------------------------------
  //
  // (1) [영역] 이 [함수내부] 인지 확인한다.
  // (2) 이 [영역] 안에서 해당 [지역변수] 를 찾는다.
  // (3) 이 [지역변수] <record-index> 를 반환한다.
  //
  //}------------------------------------------------

  //[VAR]
  //{
      int  rec_index = 0;
      int  rec_kind  = 0;

  //}

  //[초기화]
  //{
      (*rVarRecIndex) = -1;

  //}

  //[함수영역 인지 확인]
  //{
      //<record-kind> 를 구하기.
      if(REC_Field_Read2(pArea, _F_kind, NULL, &rec_kind) != true) { return(false); }

      //<record> 종류가 <_recKIND_func_def> 또는 <_recKIND_func_body> 라면 [함수 영역] 에 해당한다.
      if(!((rec_kind == _recKIND_func_def) || (rec_kind == _recKIND_func_body)))
      {
        //현재 [영역] 이 [함수영역] 이 아니므로 지금 검사하는 [단어] 는 [지역변수] 가 될수 없다.
        (*rVarRecIndex) = -1;
        return(true);

      }

      //[!]{-------------------------------------------------------------------------------------------
      //여기까지 온것은 현재 [영역] 이 [함수 영역] 인 것이므로 이 [영역] 안에서 해당하는 [지역변수] 가
      //존재하는지 확인한다.
      //}----------------------------------------------------------------------------------------------

  //}

  //[지역변수 찾기]
  //{
      //현재 [함수영역] 안에서 [이름] 과 일치하는 것을 찾는다.

      if(REC_Search_withNameAndArea(//[설계묶음] 전체를 대상으로 하므로 {DATABASE} 처음부터 검색한다.
                                    0,
                                    pWord,
                                    //[함수영역] 에서만 찾는다.
                                    pArea,
                                    //전체를 대상으로 검색한다.
                                    true,
                                    &rec_index) == false) { return(false); }

      if(rec_index >= 0)
      {
        //원하는 것을 찾았다.

        (*rVarRecIndex) = rec_index;
        return(true);

      }

  //}

  //여기까지 온것은 찾는 것이 없는 것이다.
  //함수처리 자체는 이상이 없이 종료되었다.
  return(true);

}

/*
bool __fastcall DATABASE::IS_FunctionName(struct PARSERINFO *pPARSERinfo,
                                          char              *pWORD,
                                          bool              *pBOOL,
                                          int               *pFUNCrecindex)
{
  //[2006.01.19.목][생성!!!!]{-------------------------------------------------------------
  //{DATABASE} 를 전부 뒤져서 전달받은 pWORD 가 [함수이름] 인지
  //확인하고, [함수이름] 이라면 {DATABASE} 상의 record-index 를 반환한다.
  //
  //pWORD         : 검사할 단어.
  //pBOOL         : [함수이름] 이라면면 true. 그렇지 않다면 false.
  //pFUNCrecindex : {DATABASE} 상의 발견된 record index.
  //
  //[2009.03.26.목][중요수정!!!]-----------------------------------------------------------
  //[함수이름] 의 경우는 [설계묶음] 단위 작업으로 [설계묶음] 상에서 절대
  //겹칠수 없으므로 전체 {DATABASE} 를 대상으로 검사해야 한다.
  //그렇지 않는 경우는 서로다른 문서에 함수가 기술된 경우 중복등록된다.
  //즉, "A.c" 에는 함수본체를 기술하고 "B.c" 에서 "A.h" 를 <include> 하여 사용하는경우
  //이전과 같이 [문서] 단위 검색을 하는 경우는 "B.c" 문서에는 함수가 존재하지만
  //"A.c" 문서에는 자신밖에 없으므로 결국 중복되는 것이 없는 것으로 되어
  //"A.c" 안의 함수가 중복 등록되게 된다.
  //금일 이런 문제를 발견하고 무조건 전체 {DATABASE} 를 대상으로 검사하는 것으로 수정한다.
  //}--------------------------------------------------------------------------------------

  //[방법!!!]{------------------------------------------------------------------------
  //(1) 일단 현재까지의 모든 {DATABASE} 의 전역 영역을 대상으로 검색한다.
  //    함수 선언이라면 당연히 <area: -1> 이므로 [전역영역] 만 검사하면 된다.
  //
  //(2) 해당 <record-kind> 가 <_recKIND_func_def> 나 <_recKIND_func_body> 중 하나라면
  //    함수 <record> 로 보고 원하는 것을 찾은 것이다.
  //}---------------------------------------------------------------------------------

  //[VAR]
  //{
      int  rec_index   = 0;
      int  rec_kind    = 0;
      int  start_index = 0;

  //}

  //[초기화!!!]{------------------
  //일단 반환 값을 초기화 해준다.
  (*pBOOL)         = false;
  (*pFUNCrecindex) = -1;
  //}-----------------------------

  //[name 규칙에 맞는가?]
  //{
      //가장먼저 [name 규칙] 에 맞는지 확인한다.
      //[name 규칙] 에 맞지도 않는다면 다음은 따질 것도 없다.
      //이는 처리 시간을 최소한으로 줄이기 위하여 가장 먼저 검사하는 것이다.

      if(CHECK_NameRule(pWORD) != true)
      {
        //[name 규칙] 에 조차 맞지 않으므로 사용할수 있는 [name] 이 아니다.

        //함수자체는 이상없음!!!
        return(true);

      }
  //}

  //[keyword 와 겹치는가?]
  //{
      //[예약어] 와 겹치는 것은 없는지 확인한다.
      //기본 type 은 모두 keyword 에 포함되고, 사용자가 선언한 [구조체/공용체 type]
      //이름은 {DATABASE} 상에 모두 존재 하므로 typelist[] 안의 것과 별도로 비교 검사
      //할 필요는 없다.

      if(IS_Keyword(pWORD) == true)
      {
        //[예약어] 와 겹치므로 사용가능한 [name] 이 아니다.

        //함수자체는 이상없음!!!
        return(true);

      }
  //}


  //[함수이름인가?]
  //{
      //[name 이 같은 것 찾기]
      //{
          //[함수선언] 은 global 영역만 가능하므로 global 영역에서만 검사한다.
          //name 이 같은 겻을 일단 찾는다.

          if(REC_Search_withArea_Name_inAllFile(start_index,
                                                pPARSERinfo->filelistindex, //현재 처리 중인 파일.
                                                -1,                         //영역은 global 로 설정하여 검색한다.
                                                pWORD,                      //검사할 단어.
                                                &rec_index) == false)
          {
            //함수 처리 에러!!!
            return(false);

          }
      //}

      //[같은것 찾기]
      //{
          //겹치는 것이 있는지 확인한다.
          if(rec_index > -1)
          {
            //겹치는 것이 있다면, 해당 record-kind 를 검사한다.
            if(REC_Field_Read2(rec_index, _F_kind, NULL, &rec_kind) != true)
            {
              //함수 error!!!
              return(false);

            }

            //_recKIND_func_def, _recKIND_func_body 라면 [함수 record] 이다.
            if((rec_kind == _recKIND_func_def) || (rec_kind == _recKIND_func_body))
            {
              //현재 단어는 [함수이름] 이다.
              (*pBOOL)         = true;

              //해당 함수의 rec-index 를 반환한다.
              (*pFUNCrecindex) = rec_index;

              //이상없이 처리된 것이다.
              return(true);

            }

          }
      //}
  //}

  //[!]{------------------------------------------------
  //여기까지 온것은 pWORD 는 [함수이름] 이 아닌 것이다.
  //함수는 이상없이 처리된 것이다.
  return(true);
  //}---------------------------------------------------

}
*/

bool __fastcall DATABASE::IS_HexNumber(char *pWORD)
{
  //[2005.08.28.일][생성!!!]{--------
  //[단어] 가 16 진수 인지 확인한다.
  //}--------------------------------

  if(CHECK_HexRule(pWORD) == true)
  {
    //16 진수 규칙에 맞으므로 16 진수다.
    return(true);

  }

  //여기까지 온것은 16 진수가 아닌 것이다.
  return(false);

}

bool __fastcall DATABASE::IS_BinaryNumber(char *pWORD)
{
  //[2005.08.28.일][생성!!!]{-------
  //[단어] 가 2 진수 인지 확인한다.
  //}-------------------------------

  if(CHECK_BinaryRule(pWORD) == true)
  {
    //2 진수 규칙에 맞으므로 2 진수다.
    return(true);

  }

  //여기까지 온것은 2 진수가 아닌 것이다.
  return(false);
  
}

bool __fastcall DATABASE::IS_DecNumber(char *pWORD)
{
  //[2005.08.28.일][생성!!!]{--------
  //[단어] 가 10 진수 인지 확인한다.
  //}--------------------------------

  if(CHECK_DecRule(pWORD) == true)
  {
    //10 진수 규칙에 맞으므로 10 진수다.
    return(true);

  }

  //여기까지 온것은 10 진수가 아닌 것이다.
  return(false);
 
}

bool __fastcall DATABASE::IS_FloatNumber(char *pWORD)
{
  //[2005.08.28.일][생성!!!]{-------
  //[단어] 가 [실수] 인지 확인한다.
  //}-------------------------------

  if(CHECK_FloatRule(pWORD) == true)
  {
    //[실수] 규칙에 맞으므로 [실수] 다.
    return(true);

  }

  //여기까지 온것은 [실수] 가 아닌 것이다.
  return(false);
 
}

bool __fastcall DATABASE::IS_Keyword(char *pWORD)
{
  //[2005.08.29.월][생성!!!]{---------------------------------------------
  //[단어] 가 [예약어] 인지 확인한다.
  //이미 [예약어 목록] 이 별도 준비되 있으므로 이 목록에 있는지 확인한다.
  //}---------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  for(i=0; i<OPT_keyword_list_size; i++)
  {
    if(STR_Match(keywordlist[i].kw, pWORD) == true)
    {
      //[단어] 가 [예약어] 에 해당하는 것이다.
      return(true);

    }
    
  }

  //여기까지 온것은 [예약어] 에 해당하지 않는것이다.
  return(false);

}

bool __fastcall DATABASE::IS_Operator(char *pWORD)
{
  //[2005.08.29.월][생성!!!]{---------------------------------------------
  //[단어] 가 [연산자] 인지 확인한다.
  //이미 [연산자 목록] 이 별도 준비되 있으므로 이 목록에 있는지 확인한다.
  //}---------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  for(i=0; i<OPT_operatorlist_size; i++)
  {
    if(STR_Match(operatorlist[i].op, pWORD) == true)
    {
      //[단어] 가 [연산자] 에 해당하는 것이다.
      return(true);

    }

  }

  //여기까지 온것은 [연산자] 에 해당하지 않는것이다.
  return(false);

}

bool __fastcall DATABASE::IS_Sign(char *pWORD)
{
  //[2005.08.29.월][생성!!!]{-------------------------------------------
  //[단어] 가 [기호] 인지 확인한다.
  //이미 [기호 목록] 이 별도 준비되 있으므로 이 목록에 있는지 확인한다.
  //[기호] 는 [연산자] 가 제외된 나머지 순수 [기호] 를 말한다.
  //), { 등과 같은 것들.
  //}-------------------------------------------------------------------


  //[VAR]
  //{
      int i;
  //}


  for(i=0; i<OPT_signlist_size; i++)
  {
    if(STR_Match(signlist[i].sign, pWORD) == true)
    {
      //[단어] 가 [기호] 에 해당하는 것이다.
      return(true);

    }

  }

  //여기까지 온것은 [기호] 에 해당하지 않는것이다.
  return(false);

}

bool __fastcall DATABASE::IS_Escape(char *pWORD)
{
  //[2005.08.29.월][생성!!!]{--------------
  //[단어] 가 [escape 문자] 인지 확인한다.
  //}--------------------------------------


  //[VAR]
  //{
      int i;
  //}


  for(i=0; i<OPT_escapelist_size; i++)
  {
    if(STR_Match(escapelist[i].escape, pWORD) == true)
    {
      //[단어] 가 [escape 문자] 에 해당하는 것이다.
      return(true);

    }

  }

  //여기까지 온것은 [escape 문자] 에 해당하지 않는것이다.
  return(false);

}

bool __fastcall DATABASE::IS_PreOperator(char *pWORD)
{
  //[2006.02.26.일][작성!!!]{------------------------------------------------
  //이곳에서는 단순하게 [접두연산자] 만 검사하고 역시 [접두연산자] 인
  //(typecast) 는 여기서 검사하지 않는다.
  //
  //[2012.02.19.일][중요추가!!!]---------------------------------------------
  //<sizeof [식]> 에 사용된 <sizeof> 는 [접두단항연산자] 로 본다.
  //<EXPRESSION_MatchOne()> 에서 [연산자] 처럼 [최종 자료형 크기 얻기] 의
  //[연산과정] 을 하고 결과를 [상수값] 으로 기록한다.
  //
  //<sizeof(자료형)> 의 경우는 [함수형태] 로 사용되므로 [연산자] 와 구분하고
  //<EXPRESSION_Operand()> 안에서 [피연산자] 로 처리된다.
  //}------------------------------------------------------------------------

  if(STR_Match(pWORD, "+")  == true) return(true);  //(+) 부호.
  if(STR_Match(pWORD, "-")  == true) return(true);  //(-) 부호.
  if(STR_Match(pWORD, "++") == true) return(true);  //증감.
  if(STR_Match(pWORD, "--") == true) return(true);  //감소.
  if(STR_Match(pWORD, "~")  == true) return(true);
  if(STR_Match(pWORD, "!")  == true) return(true);
  if(STR_Match(pWORD, "*")  == true) return(true);  //pointer.
  if(STR_Match(pWORD, "&")  == true) return(true);  //address.

  //[2012.02.19.일][중요추가!!!]
  //<sizeof [식]> 의 경우는 [접두단항연산자] 가 된다.
  if(STR_Match(pWORD, "sizeof") == true) return(true);

  //여기까지 온것은 해당하지 않는 것이다.
  return(false);

}

bool __fastcall DATABASE::IS_PostOperator(char *pWORD)
{
  //[2006.02.26.일][작성!!!]{--
  //[접미연산자] 를 검사한다.
  //}--------------------------

  if(STR_Match(pWORD, "++") == true) return(true);  //증감.
  if(STR_Match(pWORD, "--") == true) return(true);  //감소.

  //여기까지 온것은 해당하지 않는 것이다.
  return(false);
 
}

bool __fastcall DATABASE::IS_BiOperator(char *pWORD)
{
  //[2006.02.26.일][작성!!!]{--
  //[이항연산자] 를 검사한다.
  //}--------------------------

  if(STR_Match(pWORD, "-")   == true) return(true);
  if(STR_Match(pWORD, "->")  == true) return(true);
  if(STR_Match(pWORD, "-=")  == true) return(true);
  if(STR_Match(pWORD, "+")   == true) return(true);
  if(STR_Match(pWORD, "+=")  == true) return(true);
  if(STR_Match(pWORD, "<")   == true) return(true);
  if(STR_Match(pWORD, "<<")  == true) return(true);
  if(STR_Match(pWORD, "<<=") == true) return(true);
  if(STR_Match(pWORD, "<=")  == true) return(true);
  if(STR_Match(pWORD, ">")   == true) return(true);
  if(STR_Match(pWORD, ">>")  == true) return(true);
  if(STR_Match(pWORD, ">>=") == true) return(true);
  if(STR_Match(pWORD, ">=")  == true) return(true);
  if(STR_Match(pWORD, "=")   == true) return(true);
  if(STR_Match(pWORD, "==")  == true) return(true);
  if(STR_Match(pWORD, "!=")  == true) return(true);
  if(STR_Match(pWORD, "&")   == true) return(true);
  if(STR_Match(pWORD, "&&")  == true) return(true);
  if(STR_Match(pWORD, "&=")  == true) return(true);
  if(STR_Match(pWORD, "|")   == true) return(true);
  if(STR_Match(pWORD, "||")  == true) return(true);
  if(STR_Match(pWORD, "|=")  == true) return(true);
  if(STR_Match(pWORD, "^")   == true) return(true);
  if(STR_Match(pWORD, "^=")  == true) return(true);
  if(STR_Match(pWORD, "*")   == true) return(true);
  if(STR_Match(pWORD, "*=")  == true) return(true);
  if(STR_Match(pWORD, "/")   == true) return(true);
  if(STR_Match(pWORD, "/=")  == true) return(true);
  if(STR_Match(pWORD, "%")   == true) return(true);
  if(STR_Match(pWORD, "%=")  == true) return(true);
  if(STR_Match(pWORD, ".")   == true) return(true);

  //여기까지 온것은 해당하지 않는 것이다.
  return(false);
  
}

//[ETC]-------------------------------------------------------------------------

bool __fastcall DATABASE::GetFuncParamCount(int  pFUNCrecINDEX,
                                            int *pFUNCparamCOUNT)
{
  //[2006.03.10.금][생성!!!]{----------------------------------------
  //지정된 [record-index] 의 [함수] 정보를 처리하여 지정된 [함수] 의
  //[인수개수] 를 반환한다.
  //}----------------------------------------------------------------

  //[방법!!!]{-----------------------------------------------------------------------
  //{DATABASE} 에 [함수정보] 는 [함수 record] 를 기준으로 [인수 record] 가
  //뒤따르고 있으므로 지정된 [함수] record 로 부터 간단하게 추려낼수 있다.
  //[인수 record] 인지는 record-kind 가 _recKIND_func_param 이 된다.
  //즉, 이 _recKIND_func_param 종류의 record 의 수를 반환하면 곧 [인수개수] 가 된다.
  //}--------------------------------------------------------------------------------

  //[주의!!!]{---------------------------------------------------------------------------
  //인수가 void 인 경우는 아예 {DATAVASE} 에 [인수 record] 없이 해당 [함수 record] 만
  //위치 하는데, 이 경우 [함수 record] 다음 record 의 record-kind 가 _recKIND_func_param
  //이 아니게 된다. 이때는 [인수] 개수는 0 이 된다.
  //}------------------------------------------------------------------------------------


  //[VAR]
  //{
      int   rec_index   = -1;
      int   rec_kind    = -1;

      int   param_count = 0;
  //}


  //[param-record]{----------------------------------------------------------------
  //인수 record 가 시작하는 위치를 얻는다. [함수 record] 바로 다음 record 가 된다.
  rec_index = pFUNCrecINDEX + 1;
  //}------------------------------------------------------------------------------


  START:


  //[record-kind]{--------------------------------------------------------------------
  if(REC_Field_Read2(rec_index, _F_kind, NULL, &rec_kind) != true) { return(false); }
  //}---------------------------------------------------------------------------------

  //[param?]
  if(rec_kind == _recKIND_func_param)
  {
    //현재 record 는 [인수-record] 이다.

    //[인수] 개수 증가.
    param_count++;

    //다음 검사 record 위치로 이동.
    rec_index++;

    goto START;

  }
  else
  {
    //[인수] record 가 더이상 연속하지 않으므로 [인수개수] 를 반환하고 종료한다.
    (*pFUNCparamCOUNT) = param_count;

    return(true);

  }

  //여기까지 온것은 error!!!
  return(false);

}

void __fastcall DATABASE::Is_StructMember_withName(//[구조체] 의 <typelistindex>.
                                                   int   pStructTypelistindex,
                                                   //검색할 이름.
                                                   char *pWord,
                                                   //찾은 위치.
                                                   int  *rRecIndex)
{
  //[2006.04.20.목][생성!!!]{----------------------------------------------------
  //전달 받은 [구조체 type] 의 typelistindex 정보와 member 에 해당하는 [단어] 를
  //전달 받아서 이 [단어] 가 해당 [구조체] 의 [멤버] 인지 확인한다.
  //
  //[2009.03.28.토][완전수정!!!]
  //해당 [구조체] 의 [구성원] 인지 [이름] 으로 확인하고 해당 위치를 넘겨준다.
  //이전의 함수를 완전히 다 뜯어서 새로 구성한 것이다.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      int    motherindex = -1;

  //}

  //[모체위치 구하기]
  //{
      //먼저 typelistindex 의 정보를 참고하여 typelist[] 에서 이 [구조체] type
      //선언 정보가있는 {DATABASE} 상의 record-index 를 추출한다.
      motherindex = typelist[pStructTypelistindex].rec_index;

  //}

  //[구성원인가?]
  //{
      REC_Search_withNameAndArea(//모체의 다음 <record> 부터가 [구성원] 이 시작된다.
                                 motherindex + 1,
                                 pWord,
                                 //[모체영역].
                                 motherindex,
                                 //[모체영역] 에서만 검색한다.
                                 false,
                                 rRecIndex);

  //}

}

void __fastcall DATABASE::Is_UnionMember_withName(//[공용체] 의 <typelistindex>.
                                                  int   pUnionTypelistindex,
                                                  //검색할 이름.
                                                  char *pWord,
                                                  //찾은 위치.
                                                  int  *rRecIndex)
{
  //[2006.04.20.목][생성!!!]{----------------------------------------------------
  //전달 받은 [공용체 type] 의 typelistindex 정보와 member 에 해당하는 [단어] 를
  //전달 받아서 이 [단어] 가 해당 [공용체] 의 [멤버] 인지 확인한다.
  //
  //[2009.03.28.토][완전수정!!!]
  //해당 [공용체] 의 [구성원] 인지 [이름] 으로 확인하고 해당 위치를 넘겨준다.
  //이전의 함수를 완전히 다 뜯어서 새로 구성한 것이다.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{
      int    motherindex = -1;

  //}

  //[모체위치 구하기]
  //{
      //먼저 typelistindex 의 정보를 참고하여 typelist[] 에서 이 [공용체] type
      //선언 정보가있는 {DATABASE} 상의 record-index 를 추출한다.
      motherindex = typelist[pUnionTypelistindex].rec_index;

  //}

  //[구성원인가?]
  //{
      REC_Search_withNameAndArea(//모체의 다음 <ecord> 부터가 [구성원] 이 시작된다.
                                 motherindex + 1,
                                 pWord,
                                 //[모체영역].
                                 motherindex,
                                 //[모체영역] 에서만 검색한다.
                                 false,
                                 rRecIndex);

  //}

}

/*
bool __fastcall DATABASE::IS_StructMember_withRECINDEX(int  pStructTypelistindex,
                                                       int  pRecIndex)
{
  //[2006.07.12.수][생성!!!]{-----------------------------------------------------
  //전달 받은 [구조체 type] 의 typelistindex 정보와 member 의 record-index 정보를
  //전달 받아서 이 data 가 해당 [구조체] 의 [멤버] 인지 확인한다.
  //
  //[2006.07.30.일][수정!!!][중요!!!]---------------------------------------------
  //data 의 정보를 수집할때 recindex 는 name 을 기준으로 수집하게 된다.
  //이유는 member 인 경우는 name 이 중복 될수 있으므로 name 만으로는 어떤
  //것인지 알수 없으므로, 일단 name 에 해당하는 가장 첫번째의 recindex 값을
  //저장하게 된다. 따라서 여기서 전달받는 pRECindex 로는 직접 member 인지
  //확인할수는 없게 된다. 그러므로 이 pRECindex 에 해당하는 record 의 name
  //을 추출하여 이 name 으로 해당 member 인지 알아야 한다.
  //pRECindex 자체가 중요한 것이 아니라 실제로 이 record 의 name 이 member
  //인지 확인하는 중요한 정보가 된다.
  //
  //[2009.03.28.토][중요수정!!!]--------------------------------------------------
  //이전과 같이 [이름] 을 추출하고 다시 검사하는 복잡한 벙법을 사용하지 않고
  //이미 motherindex 가 존재하므로 이것을 비교하여 간단하게 확인하는 것으로
  //수정한다.
  //}-----------------------------------------------------------------------------

  //[VAR]
  //{
      int  i           = 0;
      int  recIndex    = -1;
      int  motherIndex = -1;

  //}

  //[구조체형의 <record-index> 얻기]
  //{
      //{DATABASE} 상의 [구조체형] 선언 위치를 찾는다.
      motherIndex = typelist[pStructTypelistindex].rec_index;

  //}

  //[구성원 인가?]
  //{
      //<record:motherindedx> 가 이미 위에서 구한 것과 같다면 [구성원] 으로 볼수 있다.
      if(motherIndex == record[pRecIndex].motherindex) { return(true);  }
      else                                             { return(false); }

  //}

}
*/

/*
bool __fastcall DATABASE::IS_UnionMember_withRECINDEX(int  pUnionTypelistindex,
                                                      int  pRecIndex)
{
  //[2006.07.12.수][생성!!!]{-----------------------------------------------------
  //전달 받은 [공용체 type] 의 typelistindex 정보와 member 의 record-index 정보를
  //전달 받아서 이 data 가 해당 [공용체] 의 [멤버] 인지 확인한다.
  //
  //[2006.07.30.일][수정!!!][중요!!!]---------------------------------------------
  //data 의 정보를 수집할때 recindex 는 name 을 기준으로 수집하게 된다.
  //이유는 member 인 경우는 name 이 중복 될수 있으므로 name 만으로는 어떤
  //것인지 알수 없으므로, 일단 name 에 해당하는 가장 첫번째의 recindex 값을
  //저장하게 된다. 따라서 여기서 전달받는 pRECindex 로는 직접 member 인지
  //확인할수는 없게 된다. 그러므로 이 pRECindex 에 해당하는 record 의 name
  //을 추출하여 이 name 으로 해당 member 인지 알아야 한다.
  //pRECindex 자체가 중요한 것이 아니라 실제로 이 record 의 name 이 member
  //인지 확인하는 중요한 정보가 된다.
  //
  //[2009.03.28.토][중요수정!!!]--------------------------------------------------
  //이전과 같이 [이름] 을 추출하고 다시 검사하는 복잡한 벙법을 사용하지 않고
  //이미 motherindex 가 존재하므로 이것을 비교하여 간단하게 확인하는 것으로
  //수정한다.
  //}-----------------------------------------------------------------------------

  //[VAR]
  //{
      int  i           = 0;
      int  recIndex    = -1;
      int  motherIndex = -1;

  //}

  //[구조체형의 <record-index> 얻기]
  //{
      //{DATABASE} 상의 [구조체형] 선언 위치를 찾는다.
      motherIndex = typelist[pUnionTypelistindex].rec_index;

  //}

  //[구성원 인가?]
  //{
      //<record:motherindedx> 가 이미 위에서 구한 것과 같다면 [구성원] 으로 볼수 있다.
      if(motherIndex == record[pRecIndex].motherindex) { return(true);  }
      else                                             { return(false); }

  //}

}
*/

bool __fastcall DATABASE::IS_Struct_Union_Member_withNAME(int   pFILELISTindex,
                                                          char *pNAME,
                                                          int  *pRECindex)
{
  //[2006.05.04.목][생성!!!]{-----------------------------------------------------
  //REC_Search_withName_inAllFile() 함수와 pNAME 을 사용하여 이 pNAME 이
  //[구조체/공용체] 의 [member] 인지 확인한다.
  //어떤 [구조체/공용체] 의 [member] 인지는 중요하지 않으며, 아무튼 [member]
  //이기만 하면 된다.
  //[member] 인지는 "motherindex >= 0" 만 확인하면 된다.
  //
  //[2009.05.13.수][중요수정!!!]--------------------------------------------------
  //API 함수를 만들다가 [인수] 에 사용된 이름의 중복시 이 함수 안의 while(1) 에서
  //빠져나오지 못하는 문제를 발견하고 이를 수정보완한다.
  //
  //[2021.02.20.토][[중요수정]****************************************************
  //}-----------------------------------------------------------------------------


  //[VAR]
  //{
      int  rec_index   = 0;
      int  motherindex = 0;

      //[2009.05.13.수][추가!!!]
      //이전의 찾은 위치를 기록한다.
      int  beforeRecIndex = -1;

  //}


  while(1)
  {
    //[2021.02.21.일][수정]{---------------------------------------------------------------------------
    //<REC_Search_withName_inAllFile()> 함수에서 <REC_Search_Member_withName_inAllFile()> 함수로 교체.
    //}------------------------------------------------------------------------------------------------
    
    if(REC_Search_Member_withName_inAllFile(rec_index, pFILELISTindex, pNAME, &rec_index) == true)
    {
      //[!]{----------------------------------------------------------------------------
      //일단 이름이 같은 것이 있다면 [구조체/공용체 member] 인지 확인한다.
      //해당 record 의 "motherindex >= 0" 이라면 [member] 에 해당하는 것으로 볼수 있다.
      //}-------------------------------------------------------------------------------

      //[motherindex 추출]
      //{
          if(REC_Field_Read2(rec_index, _F_motherindex, NULL, &motherindex) != true)
          {
            //함수 처리 error 이다.
            return(false);

          }

      //}

      if(motherindex >= 0)
      {
        //[!]{-----------------------------------
        //이 경우는 [member] 에 해당하는 것이다.
        //발견된 record-index 를 반환한다.
        //}--------------------------------------
        
        (*pRECindex) = rec_index;

        //원하는것을 찾았으므로 종료.
        return(true);

      }
      else
      {
        //[보완처리]
        //{
            //[2009.05.13.수][중요추가!!!]{---------------------------------------------------------
            //다시 발견한 위치가 이전에 찾은 위치보다 작거나 같은 경우는 찾지 못한 것으로 간주한다.
            //}-------------------------------------------------------------------------------------

            if(beforeRecIndex >= rec_index)
            {
              //[!]{-------------------------------------------------------
              //이 경우는 현재 찾은 위치가 이전에 찾은 위치이전의 것이므로
              //찾지 못한 것으로 보고 바로 종료한다.
              //}----------------------------------------------------------

              break;

            }
            else
            {
              //계속 찾기 위하여 현재 위치를 기록해 놓는다.
              beforeRecIndex = rec_index;

            }

        //}

        //[<rec_index> 가 {DB} 의 마지막 항목인가?]
        //{
            //[2021.02.20.토][중요수정/추가]{**********************************************************************
            //
            //[2018.07.25.수] 의 <EXPRESSION_DataDefault()> 함수의 중요 수정인
            //[구조체/공용체:멤버] 관련 수정과 연동된 문제일수 있으나 금일 [반인반마] 를
            //다시 빌드 하는 과정에서 아래 함수에서 발견만 문제로,
            //
            //void Gyesan_Radian_withLegOrg(...)
            //{
            //   ...
            //
            //  //[VAR]
            //  //{
            //      ...
            //                       v---이 "ld" 가 {DB} 상의 끝 레코드가 되는 경우.
            //      double   lt, lu, ld;
            //
            //  //}
            //
            //  ...
            //
            //  //[초기화]
            //  //{
            //      //다른 값을 구하는 기준값이 된다.
            //      lt = _4leg_.lt;
            //      lu = _4leg_.lu;
            //                      바로 이 "ld" 를 오류로 지정하는 문제가 발생!!! 
            //                  v---이 "ld" 는 <#include> 한 문서에 선언된 구조체의 구성원.
            //      ld = _4leg_.ld;
            //
            //      ...
            //
            //

            //1) <_4leg_.ld> 의 "ld" 를 <pFILELISTindex(현재문서)> 에서 찾는 경우
            //   "double   lt, lu, ld;" 에서 선언된 "ld" 를 위의 <REC_Search_withName_inAllFile()> 함수에서
            //   찾지만 [모체가 없는] 지역변수이기 때문에 이 부분으로 처리가 넘어 온다.
            //
            //2) 문제는 바로 이 지역변수 "ld" 가 [{DB} 상의 끝 레코드] 가 되는 관계로 계속 검사를 하기 위하여
            //   <rec_index++> 를 하는 경우 {DB} 의 범위를 초과하는 레코드를 지정하게 되고, 다시 <continue> 로
            //   검사를 시작하게 되면 <REC_Search_withName_inAllFile()> 함수에서는 당연히 찾는 것이 없게 되므로
            //   <_4leg_.ld> 에 사용된 "ld" 의 [선언부:모체] 를 찾지 못하게 되고, 결과적으로 [오류] 로 인식하게
            //   된다.
            //
            //3) 따라서, [같은이름] 을 찾았으나 [구성원] 에 해당하지 않는 <rec_index> 가 [{DB} 의 끝 레코드] 인
            //   경우의 해결은 이 함수 안에서는 해결이 안되므로, 기존의 <REC_Search_withName_inAllFile()>
            //   대신에 [같은이름의 구성원] 만 전문적으로 찾아 주는 <REC_Search_Member_withName_inAllFile()> 함수를
            //   새로 만들어서 해결됐음.
            //
            //4) 이번 경우는
            //   가) 첫번째 검색된 [이름] 이 [지역변수] 와 같으나 해당하지 않고,
            //   나) 가) 의 [지역변수] 가 우연히 {DB} 의 [끝 레코드] 인
            //   특수한 경우로 발생하는 문제로 금일 발견하고 수정한다.
            //
            //}****************************************************************************************************

        //}    

        //발견된 다음 위치로 이동 시킨다.
        rec_index++;

        //계속 검사한다.
        continue;

      }

    }
    else
    {
      //더 이상 찾을 것이 없다면 종료한다.
      break;

    }

  }

  //[!]{------------------------------------------------------------
  //여기까지 온것은 pNAME 이 [구조체/공용체 member] 가 아닌 것이다.
  (*pRECindex) = -1;

  //함수자체는 이상없이 처리된 것이다.
  return(true);
  //}---------------------------------------------------------------

}

bool __fastcall DATABASE::Is_Struct_Union_RealMember_withName(//현재 <pName> 이 있는 [문서번호].
                                                              int   pFileListIndex,
                                                              //이 [모체] 를 대상으로 <pName> 이 [구성원] 인지 검사.
                                                              int   pMotherIndex,
                                                              //<pMotherIndex> 를 대상으로 [구성원] 에 해당하는지 검사할 [이름].
                                                              char *pName,
                                                              //찾은 구성원 위치.
                                                              int  *rMemberRecIndex)
{
  //[2024.04.21.일][생성]{------------------------------------------------------------------------
  //<parser.cpp:EXPRESSION_Match_Get_MatchInfo_withINDEX()> 함수에서 [이름] 이 [모체] 에 해당하는
  //정확한 [구성원] 인지 확인하기 위하여 사용.
  //자세한 내용은 <parser.cpp:EXPRESSION_Match_Get_MatchInfo_withINDEX()> 함수안의 설명을 참고.
  //}---------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  motherIndex = 0;

      int  beforeRecIndex = -1;

  //}

  if(REC_Search_RealMember_withName_inAllFile(0, //<---{DB} 첫번째 [레코드] 부터 검색.
                                              pFileListIndex, pMotherIndex, pName, rMemberRecIndex) == true)
  {
    //[모체] 에 해당하는 [구성원] 위치는 이미 <rMemberRecIndex> 에 들어있음.

    //함수처리 자체는 이상없음.
    return(true);

  }
  else
  {
    //함수 자체의 처리 오류.
    return(false);

  }
}

/*
bool __fastcall DATABASE::IS_Struct_Union_Member_withRECINDEX(int   pRECindex,
                                                              int  *rMOTHERindex)
{
  //[2007.07.13.금][생성!!!]{-------------------------------------------------------
  //단순하게 {DATABASE} 의 recordindex 를 전달받아서 해당 개체가 [구조체/공용체] 의
  //[구성원] 인지만 확인한다.
  //종류는 상관이 없으며 단지 [구성원] 인가만 확인하면 된다.
  //즉, "motherindex > 0" 인 경우는 무조건 [구성원] 으로 볼수있다.
  //이 함수는 해당 개체의 motherindex 를 구해서 반환하는 것까지만 처리한다.
  //}-------------------------------------------------------------------------------

  //[motherindex 추출]
  //{
      if(REC_Field_Read2(pRECindex, _F_motherindex, NULL, rMOTHERindex) != true)
      {
        //함수 처리 error 이다.
        return(false);

      }

  //}

  //함수자체는 이상없이 처리되었다.
  return(true);

}
*/

bool __fastcall DATABASE::REC_Search_Member_withName_inAllFile(//검색을 시작할 <record-index>.
                                                               int   pStartIndex,
                                                               //문서 번호.
                                                               int   pFileListIndex,
                                                               //검사할 [이름].
                                                               char *pName,
                                                               //찾은 <record-index>.
                                                               int  *pRecIndex)
{
  //[2021.02.21.일][생성]{--------------------------------------------------------------------------------------
  //<REC_Search_withName_inAllFile()> 를 바탕으로 <pName> 이 같은 [구성원(MotherIndex > 0)] 만 대상으로 찾는다.
  //}-----------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  recIndex         = -1;
      int  incCount         =  0;
      int  incFileListIndex = -1;
      int  motherIndex      = -1;
      int  i                =  0;
      

  //}

  //[지정 문서에서 검색]
  //{
      //[검색]
      //{
          //[!]{-----------------------------------------------------
          //우선 처음 인수로 지정된 [문서] 안에 존재하는지 검색한다.
          //}--------------------------------------------------------

          if(REC_Search_withName_inFile(pStartIndex, pFileListIndex, pName, &recIndex) == false)
          {
            (*pRecIndex) = -1;

            //함수 오류.
            return(false);

          }

      //}

      //[motherindex 추출]
      //{
          if(REC_Field_Read2(recIndex, _F_motherindex, NULL, &motherIndex) != true)
          {
            //함수 오류.
            return(false);

          }

      //}

      //[이름이 같고 구성원인 경우만 반환]
      //{
          if((recIndex >= 0) && (motherIndex >= 0))
          {
            //[!]{---------------------------------------------------
            //원하는 것을 찾은 것이므로 찾은 <record-index> 를 반환.
            //}------------------------------------------------------

            (*pRecIndex) = recIndex;
            return(true);

          }

      //}

  //}

  //[!]{-----------------------------------------------------------------------
  //여기까지 온것은 지정된 현재 file 에는 없는 것이므로, 이 file 이 include 한
  //file 안에 있는지 검사한다.
  //}--------------------------------------------------------------------------

  //[<include 문서> 존재 확인]
  //{
      //[!]{-------------------------------------------
      //이 file 에 include 한 [문서] 의 개수를 얻는다.
      //}----------------------------------------------

      incCount = filelist[pFileListIndex].include_list_count;

      //현재 이 file 안에 include 된 file 이 있는지 확인한다.
      if(incCount <= 0)
      {
        //현재 file 에도 없고 이 file 이 include 한 file 이 없으므로 찾는것이 없다.
        (*pRecIndex) = -1;

        //이상없이 검색을 마친 것이다.
        return(true);

      }

  //}

  //[<include> 된 [문서] 안에 존재하나?]
  //{
      //[중요!!!]{-------------------------------------------------------------
      //<include> 된 [문서] 안에 또다른 <include> 된 [문서] 가 있을수 있으므로
      //여기서는 REC_Search_withName_inFile() 함수가 아니고 지금 함수
      //REC_Search_withName_inAllFile() 함수를 재귀호출해서 사용해야 한다.
      //모든 <include> 된 [문서] 까지 완벽하게 검색하게 된다.
      //}----------------------------------------------------------------------

      //[!]{---------------------------------------------
      //바로 위에서 추출한 incCount 정보를 사용한다.
      //현재 file 안에 include 된 file 만 대상으로 한다.
      //}------------------------------------------------

      for(i = 0; i < incCount; i++)
      {
        //<include> 된 [문서] 의 <filelist-index> 를 구한다.
        incFileListIndex = filelist[pFileListIndex].include_list[i];

        //[검색]
        //{
            //[!]{-------------------------------------------------------------------
            //<include> 된 모든 [문서] 까지 검색한다.
            //<include> 된 [문서] 의 경우는 무조건 {DATABASE} 처음(0) 부터 검색한다.
            //}----------------------------------------------------------------------

            if(REC_Search_Member_withName_inAllFile(0, incFileListIndex, pName, &recIndex) == false)
            {
              (*pRecIndex) = -1;
              return(false);

            }

            if(recIndex > -1)
            {
              //원하는 것을 찾은 것이다.

              (*pRecIndex) = recIndex;
              return(true);

            }

        //}

      }

  //}

  //[!]{---------------------------------------------------
  //여기까지 온것은 include 된 모든 file 에도 없는 것이다.
  //}------------------------------------------------------

  (*pRecIndex) = -1;

  //검색은 이상없이 마친것이다.
  return(true);

}

bool __fastcall DATABASE::REC_Search_RealMember_withName_inFile(//검색을 시작할 <record-index>.
                                                                int   pStartIndex,
                                                                //문서 번호.
                                                                int   pFileListIndex,
                                                                //검사 대상 [모체].
                                                                int   pMotherIndex,
                                                                //검사할 [이름].
                                                                char *pName,
                                                                //찾은 <recordIndex>.
                                                                int  *rRecIndex)
{
  //[2024.04.21.일][생성]{------------------------------------------------------------------------
  //<REC_Search_withName_inFile()> 함수를 바탕으로 만들어 졌으며, <pFileListIndex> 의 [문서] 에서
  //<pMotherIndex> 에 해당하는 [모체] 안에 <pName> 에 해당하는 [구성원] 의 위치를 찾아서 반환.
  //}---------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int i;

  //}

  //[<pStartIndex> 가 현재까지 정리된  {DB} 범위 안에 존재하나?]
  //{
      if(!((0 <= pStartIndex) && (pStartIndex < record_count)))
      {
        //지정 범위를 벘어났으므로 처리하지 않는다.
        (*rRecIndex) = -1;
        return(false);

      }

  //}

  //[<pFileListIndex> 가 {FILELIST} 범위 안인가?]
  //{
      //[참고]{----------------------------------------------------------------
      //0 번 file 은 "GIGYEIN" file 로 이는 SYSTEM 예약이므로 사용하지 않는다.
      //}----------------------------------------------------------------------

      if(!((0 < pFileListIndex) && (pFileListIndex < filelist_count)))
      {
        //지정 위치가 범위를 벘어났으므로 처리하지 않는다.
        (*rRecIndex) = -1;
        return(false);

      }

  //}

  //[검색]
  //{
      //[!]{--------------------------------------------------------
      //{DB} 상에서 <pMotherIndex> 를 갖는 <pName> 찾기.
      //단, 지정된 <pFileListIndex> 의 [문서] 만을 대상으로 찾는다.
      //}-----------------------------------------------------------

      for(i = pStartIndex; i < record_count; i++)
      {
        //<pFileListIndex> 에 해당하는 [문서] 만 대상으로 처리.
        if(pFileListIndex == record[i].filelistindex)
        {
          //<pMotherIndex>, <pName> 이 모두 일치하는 [레코드] 찾기.
          if((record[i].motherindex == pMotherIndex) && (STR_Match(pName, record[i].name) == true))
          {
            //[!]{--------------------------------------------------------
            //원하는 [구성원] 을 찾은 것이므로 해당 [레코드번호] 를 반환.
            //}-----------------------------------------------------------

            (*rRecIndex) = i;

            return(true);

          }

        }

      }
  //}

  //[!]{-------------------------------------------------
  //여기까지 온것은 조건에 맞는 [구성원] 을 찾지 못한것.
  (*rRecIndex) = -1;
  //}----------------------------------------------------

  //검색 자체는 오류 없이 마친것.
  return(true);

}

bool __fastcall DATABASE::REC_Search_RealMember_withName_inAllFile(//검색을 시작할 <record-index>.
                                                                   int   pStartIndex,
                                                                   //문서 번호.
                                                                   int   pFileListIndex,
                                                                   //검사 대상 [모체].
                                                                   int   pMotherIndex,
                                                                   //검사할 [이름].
                                                                   char *pName,
                                                                   //찾은 <recordIndex>.
                                                                   int  *rRecIndex)
{
  //[2024.04.21.일][생성]{-------------------------------------------------------------------------------------
  //<REC_Search_Member_withName_inAllFile()> 를 바탕으로 <pMotherIndex> 에 속한 [구성원] 인 <pName> 을 찾는다.
  //
  //<parser.cpp:EXPRESSION_Match_Get_MatchInfo_withINDEX()> 함수안의 같은 날짜 내용을 참고.
  //}----------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  recIndex         = -1;
      int  incFileCount         =  0;
      int  incFileListIndex = -1;
      int  motherIndex      = -1;
      int  i                =  0;

  //}

  //[지정 문서에서 검색]
  //{
      if(REC_Search_RealMember_withName_inFile(pStartIndex, pFileListIndex, pMotherIndex, pName, &recIndex) == false)
      {
        (*rRecIndex) = -1;

        //함수 오류.
        return(false);

      }
      else
      {
        if(recIndex > -1)
        {
          //[!]{---------------------------------------------------------------------------
          //이 문서에서 조건에 해당하는 것을 찾은 경우는 여기서 결과를 반환하고 바로 종료.
          //}------------------------------------------------------------------------------

          (*rRecIndex) = recIndex;

          return(true);

        }

      }

      //[!]{------------------------------------------------------------------------
      //여기까지 온것은 현재 <pFileListIndex> 의 [문서] 안에 존재하지 않으므로 계속
      //<#include> 된 다른 문서안에 존재하는지 계속 검사한다.
      //}---------------------------------------------------------------------------

  //}

  //[!]{-------------------------------------------------------------------------------------
  //여기까지 온것은 지정된 <pFileListIndex> 문서에 없는 것이므로, 이 <pFileListIndex> 문서가
  //<#include> 한 모든 [문서] 를 대상으로 검사한다.
  //}----------------------------------------------------------------------------------------

  //[<#include 문서> 안에 존재하는지 확인]
  //{
      //[!]{--------------------------------------------------------
      //이 <pFileListIndex> 에서 <#include> 한 [문서] 의 개수 얻기.
      //}-----------------------------------------------------------

      incFileCount = filelist[pFileListIndex].include_list_count;

      //<#include> 된 문서가 존재하나?
      if(incFileCount <= 0)
      {
        //[!]{------------------------------------------------------------
        //이 경우는 현재 지정 [문서] 에도 없고 이 [문서] 가 <#include> 한
        //[문서] 자체가 없으므로, 찾는 것이 존재하지 않는것으로 본다.
        //}---------------------------------------------------------------

        (*rRecIndex) = -1;

        //함수 처리 자체는 이상없이 마친것.
        return(true);

      }

  //}

  //[<#include> 된 [문서] 안에 존재하나?]
  //{
      //[중요]{----------------------------------------------------------------------------------------------
      //이 경우는 현재 [문서] 가 <#include> 한 [문서] 가 존재하므로, 이 [문서] 를 대상으로 검색.
      //
      //단, <#include> 된 [문서] 안에 또 다른 <include> 된 [문서] 가 있을수 있으므로 여기서는
      //<REC_Search_withName_inFile()> 함수가 아니고, 지금 함수 <REC_Search_RealMember_withName_inAllFile()>
      //함수를 [재귀호출] 해서 처리한다.
      //
      //모든 <#include> 된 [문서] 까지 완벽하게 검색하게 된다.
      //}----------------------------------------------------------------------------------------------------

      //[!]{******************************************************************************************************
      //바로 위에서 추출한 <incDocCount> 정보를 사용하고, 현재 [문서] 안에 <#include> 된 [문서] 만 대상으로 처리.
      //}*********************************************************************************************************

      for(i = 0; i < incFileCount; i++)
      {
        //<include> 된 [문서] 의 <filelist-index> 를 구한다.
        incFileListIndex = filelist[pFileListIndex].include_list[i];

        //[검색]
        //{
            //[!]{---------------------------------------------------------------
            //<#include> 된 모든 [문서] 까지 검색한다.
            //단, <#include> 된 [문서] 의 경우는 무조건 {DATABASE}[0] 부터 검색.
            //}------------------------------------------------------------------

            if(REC_Search_RealMember_withName_inAllFile(0, incFileListIndex, pMotherIndex, pName, &recIndex) == false)
            {
              //함수처리 오류인 경우.
              (*rRecIndex) = -1;
              return(false);

            }
            else
            {
              if(recIndex > -1)
              {
                //[!]{----------------------------
                //조건에 해당하는 것을 찾은 경우.
                //}-------------------------------

                (*rRecIndex) = recIndex;

                return(true);

              }

            }

        //}

      }

  //}

  //[!]{----------------------------------------------------
  //여기까지 온것은 <#include> 된 모든 [문서] 에도 없는 것.
  //}-------------------------------------------------------

  (*rRecIndex) = -1;

  //검색은 이상없이 마친것이다.
  return(true);

}

/*
위 함수 만들기 이전것.
//[2024.04.21.일][주석처리]
bool __fastcall DATABASE::REC_Search_RealMember_withName_inAllFile(//검색을 시작할 <record-index>.
                                                                   int   pStartIndex,
                                                                   //문서 번호.
                                                                   int   pFileListIndex,
                                                                   //검사 대상 [모체].
                                                                   int   pMotherIndex,
                                                                   //검사할 [이름].
                                                                   char *pName,
                                                                   //찾은 <recordIndex>.
                                                                   int  *rRecIndex)
{
  //[2024.04.21.일][생성]{-------------------------------------------------------------------------------------
  //<REC_Search_Member_withName_inAllFile()> 를 바탕으로 <pMotherIndex> 에 속한 [구성원] 인 <pName> 을 찾는다.
  //
  //<parser.cpp:EXPRESSION_Match_Get_MatchInfo_withINDEX()> 함수안의 같은 날짜 내용을 참고.
  //}----------------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int  recIndex         = -1;
      int  incFileCount         =  0;
      int  incFileListIndex = -1;
      int  motherIndex      = -1;
      int  i                =  0;

  //}

  //[지정 문서에서 검색]
  //{
      //[검색]
      //{
          //[!]{------------------------------------------------
          //우선 지정 <pFileListIndex> 문서 에 존재하는지 검색.
          //}---------------------------------------------------

          if(REC_Search_RealMember_withName_inFile(pStartIndex, pFileListIndex, pMotherIndex, pName, &recIndex) == false)
          {
            (*rRecIndex) = -1;

            //함수 오류.
            return(false);

          }

      //}

      //[<motherindex> 추출]
      //{
          if(REC_Field_Read2(recIndex, _F_motherindex, NULL, &motherIndex) != true)
          {
            //함수 오류.
            return(false);

          }

      //}

      //[<pName> 에 해당하는 항목이 지정 [모체] 의 [구성원] 인가?]
      //{
          if((recIndex >= 0) && (motherIndex == pMotherIndex))
          {
            //[!]{--------------------------------------------------
            //원하는 것을 찾은 것이므로 찾은 <recordIndex> 를 반환.
            //}-----------------------------------------------------

            (*rRecIndex) = recIndex;
            return(true);

          }

      //}

  //}

  //[!]{-------------------------------------------------------------------------------------
  //여기까지 온것은 지정된 <pFileListIndex> 문서에 없는 것이므로, 이 <pFileListIndex> 문서가
  //<#include> 한 모든 [문서] 를 대상으로 검사한다.
  //}----------------------------------------------------------------------------------------

  //[<#include 문서> 안에 존재하는지 확인]
  //{
      //[!]{--------------------------------------------------------
      //이 <pFileListIndex> 에서 <#include> 한 [문서] 의 개수 얻기.
      //}-----------------------------------------------------------

      incFileCount = filelist[pFileListIndex].include_list_count;

      //<#include> 된 문서가 존재하나?
      if(incFileCount <= 0)
      {
        //[!]{------------------------------------------------------------
        //이 경우는 현재 지정 [문서] 에도 없고 이 [문서] 가 <#include> 한
        //[문서] 자체가 없으므로, 찾는 것이 존재하지 않는것으로 본다.
        //}---------------------------------------------------------------

        (*rRecIndex) = -1;

        //함수 처리 자체는 이상없이 마친것.
        return(true);

      }

  //}

  //[<#include> 된 [문서] 안에 존재하나?]
  //{
      //[중요]{----------------------------------------------------------------------------------------------
      //이 경우는 현재 [문서] 가 <#include> 한 [문서] 가 존재하므로, 이 [문서] 를 대상으로 검색.
      //
      //단, <#include> 된 [문서] 안에 또 다른 <include> 된 [문서] 가 있을수 있으므로 여기서는
      //<REC_Search_withName_inFile()> 함수가 아니고, 지금 함수 <REC_Search_RealMember_withName_inAllFile()>
      //함수를 [재귀호출] 해서 처리한다.
      //
      //모든 <#include> 된 [문서] 까지 완벽하게 검색하게 된다.
      //}----------------------------------------------------------------------------------------------------

      //[!]{******************************************************************************************************
      //바로 위에서 추출한 <incDocCount> 정보를 사용하고, 현재 [문서] 안에 <#include> 된 [문서] 만 대상으로 처리.
      //}*********************************************************************************************************

      for(i = 0; i < incFileCount; i++)
      {
        //<include> 된 [문서] 의 <filelist-index> 를 구한다.
        incFileListIndex = filelist[pFileListIndex].include_list[i];

        //[검색]
        //{
            //[!]{---------------------------------------------------------------
            //<#include> 된 모든 [문서] 까지 검색한다.
            //단, <#include> 된 [문서] 의 경우는 무조건 {DATABASE}[0] 부터 검색.
            //}------------------------------------------------------------------

            if(REC_Search_RealMember_withName_inAllFile(0, incFileListIndex, pMotherIndex, pName, &recIndex) == false)
            {
              //함수처리 오류인 경우.
              (*rRecIndex) = -1;
              return(false);

            }
            else
            {
              if(recIndex > -1)
              {
                //[!]{----------------------------
                //조건에 해당하는 것을 찾은 경우.
                //}-------------------------------

                (*rRecIndex) = recIndex;

                return(true);

              }

            }

        //}

      }

  //}

  //[!]{----------------------------------------------------
  //여기까지 온것은 <#include> 된 모든 [문서] 에도 없는 것.
  //}-------------------------------------------------------

  (*rRecIndex) = -1;

  //검색은 이상없이 마친것이다.
  return(true);

}
*/

void __fastcall DATABASE::GET_FunctionLoaclTotal(int         pFuncRecIndex,
                                                 long long  *rLocalTotal)
{
  //[2008.11.01.토][생성!!!]{----------------------------------------------------------------------------
  //지정된 함수 index 를 받아서 해당 함수의 현 시점에서의 Local Data 의 총 크기를 구해서 반환한다.
  //이 함수는 반드시 함수 안의 data 선언 부분이 모두 끝난 상태에서 사용해야 하며, 인수, 지역변수
  //의 모든 크기를 합하면 된다.
  //ANSI-C 는 함수 "{" 부터 처음에만 지역변수를 선언할수 있으므로 함수 끝까지 가지 않아도 data 선언이
  //모두 끝나는 위치에서 바로 이 함수를 사용하여 총 크기를 구할수 있는 것이다.
  //TREE_FunctionBody() 함수에서 TREE_DataDefinition() 이 끝나면 바로 이 함수를 호출하여 해당 함수의
  //총 지역변수 크기를 구한다.
  //
  //기계닉스 C 에서는 [인수] 도 [지역변수] 에 포함되는다는 것에 주의한다.

  //[2008.11.06.목][중요주의!!!]
  //함수 record 에 함수안의 [지역변수 총 크기] 를 size 에 할당하는 것은 여기서 하지 않고
  //이 함수는 사용하는 TREE_FunctionBody() 함수와 사용되는 TREE_FunctionDefinition() 함수에서 처리된다.
  //
  //[2009.02.06.금][중요 수정!!!]------------------------------------------------------------------------
  //[함수선언] 이 먼저 오고 [본체선언] 이 나중에 오는 경우는 서로 {DATABASE} 상에서 서로의 정보가 연결되
  //있지 않게 된다. 따라서, [함수] 에 사용된 [지역변수] 의 총 크기를 구하는데 있어서 무조건
  //[함수 record] 다음부터 구하는 것은 [선언] 이 먼저 오고 [본체선언] 이 나중에 오는 경우는
  //<record> 가 연속적이지 않게 되므로 제대로된 값이 계산되지 않는다.
  //
  //{DATABASE}=================================================================
  //
  // 함수선언 record.
  // 인수0 record.      <---[인수] 는 함수 record 바로 다음부터 시작한다.
  // 인수1 record.
  //
  // ...다른 정보.
  // ...다른 정보.
  //
  // 지역변수0 record.  <---해당 함수의 지역 변수는 { } 안에 있으므로 떨어져 있을수 있다.
  // 지역변수1 record.
  //
  // ... 다른 정보.
  //
  //===========================================================================
  //
  //와 같은 형식이 된다.
  //그러므로, 무조건 [함수 record] 다음부터 검사하는 것이 아니라
  //[함수인수] 부분과 [함수지역] 부분으로 나누어 두번에 걸쳐 처리해야 한다.
  //
  // 1) 이 함수 record-index 를 <area> 정보로 갖는 <record> 를 찾는다.
  // 2) 이 위치부터 이전 방법으로 [지역 변수 총 크기] 를 계산하여 반환한다.
  //
  //의 방법으로 처리하면 된다.
  //
  //[2012.04.06.금][중요수정!!!]------------------------------------------------------------------------
  //함수가 한개뿐이고, 인수는 있으나 [지역변수] 가 존재하지 않는 경우는
  //{DB} 끝까지 검사해도 <funcAreaStartIndex> 값을 확정할수 없으므로 [지역변수]
  //처리부에서 [오류] 가 발생하는 부분 수정.
  //
  //이는 <define> 정의 검사를 단순화 고속화 하도록 <Parser.cpp:Get_NextWord()> 함수를
  //수정하는 과정에서 <DEFINELIST_Search_withName_inAllFile()> 대신 새로 만든
  //<DEFINELIST_Search_withName()> 함수를 사용중 오류를 발견하고 수정한다.
  //
  //BCB 상의 내부 문제인듯 하고 이전에는 <funcAreaStartIndex> 이 [선언동시초기화] 하지
  //않았음에도 자동적으로 <0> 으로 초기화 되어 문제가 없었으나, 금일 새로 수정된
  //<Parser.cpp:Get_NextWord() 함수를 사용시 오류가 발생하는 과정을 추적중 알아내고 수정.
  //같은 날짜 수정 내용을 참고.
  //}----------------------------------------------------------------------------------------------------

  //[방법]{------------------------------------------------------------------------
  //SIZE_Data() 함수 한개로 간단하게 해당 data 의 byte 단위 크기를 쉽게 알수 있다.
  //{DATABASE} 안에 record.size 필드도 같이 채워준다.
  //}------------------------------------------------------------------------------


  //[VAR]
  //{
      int         i;
      long long   dataSize;
      long long   dataTotalSize = 0;

      //[2009.02.06.금][추가!!!]
      int         funcAreaStartIndex;

  //}


  //[함수 인수 처리]
  //{
      for(//[인수] record 는 [함수] record 다음 record 부터 시작된다.
          i = pFuncRecIndex + 1;
          //해당 함수안의 data 만 대상으로 한다.
          record[i].area == pFuncRecIndex;
          i++)
      {
        //[추가주소 얻기]
        //{
            //[2008.11.06.목][추가!!!]{-----------------------------------
            //이 위치에서 바로 현재 [지역변수] 의 [추가주소] 를 할당한다.
            //}-----------------------------------------------------------

            //이전 까지의 [지역변수] 총 크기가 지금 [지역변수] 의 [추가주소] 가 된다.

            record[i].address = dataTotalSize;

        //}

        //해당 data 의 크기를 구한다.
        SIZE_Data(i, &dataSize);

        //[record 필드 입력]
        //{
            record[i].size = dataSize;

        //}

        //지역 변수 크기를 계속 더한다.
        dataTotalSize += dataSize;

      }

  //}

  //[함수 지역 변수 처리]
  //{
      //[2009.02.06.금][추가!!!]{--------------------------------------------------------------------
      //[지역변수] 는 항상 [함수 record] 와 연속적으로 영역이 존재 하는 것이 아니므로
      //일단, [함수 recordindex] 를 <area> 정보로 갖는 <record> 의 시작 위치를 얻어서 처리해야 한다.
      //단, [함수지역] 영역은 "{ --- }" 사이의 영역이므로 항상 연속적이다.
      //}--------------------------------------------------------------------------------------------

      //[함수 지역영역 찾기]
      //{
          //[2012.04.06.금][중요수정!!!]{--------------------------------
          //[지역변수] 가 없고 함수가 한개만 존재하는 경우는 {DB} 끝까지
          //검사해도 <funcAreaStartIndex> 값을 확정할수 없으므로
          //다음 처리부에서 [오류] 발생하는 부분 수정.
          //}------------------------------------------------------------

          //이전의 인수 다음부터 계속 검사하여 찾는다.
          for( ; i < record_count; i++)
          {
            //[함수] recindex 값을 <area> 값으로 갖는 것이 [함수] 의 [지역변수] 들이다.
            if(record[i].area == pFuncRecIndex)
            {
              funcAreaStartIndex = i;

              //[2012.04.06.금][중요수정!!!]{-------------------------
              //<funcAreaStartIndex> 값을 얻은 경우는 바로 종료.
              //이는 함수가 하나밖에 없고 안에 지역변수가 없는 경우는
              //{DB} 를 이미 넘어선 경우라 <funcAreaStartIndex> 값이
              //확정되지 않고 다음으로 넘어가는 것을 막기 위한것.
              //아래의 for() 문 종료 설명을 참고.
              goto lbLocalVar;
              //절대 <break;> 로 처리하지 않는다.
              //break;
              //}-----------------------------------------------------

            }

          }

          //[중요수정/보완!!!]{---------------------------------------------------
          //이 위치로 온 것은 이미 {DB} 끝가지 다 검사한 것이다.
          //문서에 "void main(void) {  }" 한개만 처리하고 내부에 [지역변수] 가
          //한개도 없는 경우는 위에서 이미 [인수] 를 검사한 상태이므로
          //[지역변수] 부분을 검사할 필요가 없으며 자동으로 선언된 [지역변수] 가
          //없기 때문에 {DB} 끝가지 검사하게 되나 더이상 해당 [함수영역] 을 갖는
          //항목이 없게 되어 <funcAreaStartIndex> 값이 확정되지 않아 아래부분에서
          //오류가 발생하게 된다.
          //금을 이 문제를 발견하고 수정한다.
          //더이상 지역변수가 없으므로 여기서 종료.
          goto lbEnd;
          //}---------------------------------------------------------------------

      //}

      //[2012.04.06.금][추가!!!]
      lbLocalVar:

      for(//[함수지역] 부터 시작한다.
          i = funcAreaStartIndex;
          //해당 함수안의 data 만 대상으로 한다.
          record[i].area == pFuncRecIndex;
          i++)

      {
        //[추가주소 얻기]
        //{
            //[!]{--------------------------------------------------------
            //이 위치에서 바로 현재 [지역변수] 의 [추가주소] 를 할당한다.
            //}-----------------------------------------------------------

            //이전 까지의 [지역변수] 총 크기가 지금 [지역변수] 의 [추가주소] 가 된다.

            record[i].address = dataTotalSize;

        //}

        //해당 data 의 크기를 구한다.
        SIZE_Data(i, &dataSize);

        //[record 필드 입력]
        //{
            record[i].size = dataSize;

        //}

        //지역 변수 크기를 계속 더한다.
        dataTotalSize += dataSize;

      }

  //}

  //[2012.04.06.금][추가!!!]
  lbEnd:
                                  
  //여기까지 해당 함수안의 모든 [지역변수] 크기 총합을 얻었다.

  //[크기 반환]
  //{
      if(rLocalTotal != NULL) { (*rLocalTotal) = dataTotalSize; }

  //}

  return;

}

void __fastcall DATABASE::Get_1st_FunctionParamListStr(int   pFuncRecIndex,
                                                       char  rParamListStr[])
{
  //[2008.12.14.일][생성!!!]{--------------------------------------------------------------------------
  //1차 번역시에 [함수본체시작] 부분의 번역시 추가되는 "{ param-list }" 정보 문자열을 만들어 반환한다.
  //
  // FD.x.{: <LocalTotal> { param-list }
  //
  //와 같이 [1차번역] 시에 사용된다.
  //}--------------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //{expdatabase} 의 [함수사용] 을 위하여 포인터로 하나 선언해 준다.
      //내부의 다른 정보는 불필요하며 오직 함수만 사용하기 위한 것이다.
      class  EXPDATABASE *expdatabase;

      char   symbol[OPT_wordStrSize];

      int    i;

  //}

  //[저장소 초기화]
  //{
      //반환할 문자열의 저장소를 일단 초기화 한다.
      STR_Assign(rParamListStr, "{ ");

  //}

  for(//[인수] record 는 [함수] record 다음 record 부터 시작된다.
      i = pFuncRecIndex + 1;
      //[인수] record 는 [종류] 가 <_recKIND_func_param> 으로 정의되 있다.
      record[i].kind == _recKIND_func_param;
      i++)
  {
    //[인수의 1차번역 기호 얻기]
    //{
        //[인수] 의 해당 [1차번역기호] 를 얻는다.
        expdatabase->Data(//지금 이 {database} 자체를 대상으로 처리한다.
                          this,
                          //현재 {database} 상의 [인수] record-index.
                          i,
                          //[인수] 의 [1차번역기호] 얻기.
                          symbol,
                          //단지 [1차번역기호] 만 얻는다.
                          true);

     //}

     //[param-list 만들기]
     //{
         //각각의 [단어] 가 [공백] 한개를 [구분자] 로 구분될수 있게 문자열로 합성한다.
         STR_Add(rParamListStr, symbol);
         STR_Add(rParamListStr, " ");

     //}

  }

  //[param-list 완성]
  //{
      STR_Add(rParamListStr, "} ");

  //}

  //여기까지 이미 <param-list> 가 문자열로 함성되어 반환되었다.

  return;

}

void __fastcall DATABASE::Get_FunctionParamSize(//함수의 record-index.
                                                int         pFuncRecIndex,
                                                //[인수] 의 순번(BASE : 0).
                                                int         pParamXst,
                                                //해당 [인수] 의 크기.
                                                long long  *rParamSize)
{
  //[2008.12.16.화][생성!!!]{--------------------------------------------------------
  //해당 [함수] 의 해당 [순번] 의 [인수] 크기를 얻는다.
  //이는 FU.x ( ), FR.x ( ) 의 [ASM 번역] 시 "push" 사용에서 정확한 [인수] 의 크기를
  //기술하기 위하여 필요하다.
  //
  //[인수] record 는 [함수] record 바로 다음부터 시작한다.
  //}--------------------------------------------------------------------------------

  //해당 [함수] 의 지정 순번의 [인수] 크기를 반환한다.
  (*rParamSize) = record[pFuncRecIndex +
                  //[인수] 는 [함수] 다음 record 부터 시작한다.
                  1 +
                  pParamXst].size;

  return;

}

//[FILE]{------------------------------------------------------------------
//file 을 처리하기 위한 전용 함수를 배치한다.
//include 문으로 file 을 call 하는 경우 사용되나 내부 적으로 자동 처리해야
//할 것이 많으므로 별도의 함수를 만든다.
//파일 처리를 위하여 어쩔수 없이 AnsiString 등 라이브러리를 사용 한다.
//}------------------------------------------------------------------------

bool __fastcall DATABASE::FILE_Call_Enter(char *pFILEname)
{
  //[2005.09.09.금][생성!!!]{-------------------------------------------------------
  //전달받은 file 을 열어주고 그에 따른 부가적인 처리를 수행한다.
  //이 함수는 file 을 열때 사용되고, 처음 parser() 가 기동할때 main() 이 있는
  //[소스파일] 을 읽어 들일때와 #include 문으로 file 을 call 하는 경우만
  //사용된다. 실제 file 을 여는 경우는 이 두가지 경우 밖에는 없다.
  //
  //원래 순수하게 C, C++ 만으로 작성을 해야 하나, 파일 입출력을 위하여 부득이
  //하게 Borland 의 라이브러리를 사용해야 하므로 AnsiString 등을 허용한다.
  //
  //[2005.09.12.월][대폭수정!!!]{---------------------------------------------------
  //parserinfostack[] 을 기준으로 다시 정리하므로 이 함수를 대폭 수정한다.
  //
  //[2012.05.27.일][중요수정!!!]----------------------------------------------------
  //<FileOpen()>, <FileSeek()> API 는 오류 발생시 <-1> 를 반환한다.
  //
  //처리하는 문서들과 같은 하드디스크안의 [동영상 재생] 시 이 문서들에 빈번하게
  //접근하는 경우 [오류] 가 발생하며 <-1> 을 반환한다.
  //
  //이는 [실시간 선언 정보판] 을 확인하다 간혹 [오류] 가 발생하는 원인을 추적중
  //알아낸 것으로 <Parser()> 시 <include> 된 문서등 API 가 많은 경우 <함수묶음.h>
  //문서를 수십번을 열고 닫기 하게 되는데 이때 [빈도] 가 높은 탐색이 간혹 [오류] 가
  //발생하고 <-1> 을 반환한다.
  //
  //물리적인 디스크에 여러개의 동시 작업 하는 [문서] 가 존재하는 경우 접근오류임을
  //발견하였다.
  //
  //이는 거의 1회만 발생하는 것으로 간단하게 다시 처리하는 것으로 처리하였다.
  //아무 이상없이 잘 된다.
  //}-------------------------------------------------------------------------------

  //[주의!!!]{-----------------------------------------------------------------
  //compile 시에 처리할 파일을 저장하는 buf[] 는 하나만 사용하므로 새로운 파일
  //을 열기 위해서는 이전의 내용을 삭제해 주어야 한다.
  //즉, 필요한 파일만 열고 그외는 닫는다. compile 과정에서는 언제나 한개의
  //파일만을 대상으로 하므로, memory 를 낭비하지 않고 file 을 효과적으로 관리
  //하기 위한 것이다.
  //}--------------------------------------------------------------------------

  //[부가처리내용]{------------------------------------------------------
  /* 1. 새로운 파일을 열기 위하여 현재 열어 놓은 파일파일/parserinfo 를
        (나중에 다시 돌아와야 하므로) parserinfostack[] 에 Push 한다.

     2. filelist[] 의 내용을 수정.
        이곳에 파일을 추가 하는 경우는 중복여부를 검사해 주어야 한다.
        다음 3번에서 filelistindex 로 filename 을 지정하므로 여기서 먼저
        filename 이 먼저 정리되 있어야 한다.

     3. parserinfo.buf(버퍼 포인터), parserinfo.filelistindex 수정.

     4. 기타 처리.
  */
  //}--------------------------------------------------------------------


  //[file 유/무 확인]
  //{
      //전달받은 file 이 존재 하는지 확인한다.
      if(FileExists((AnsiString)pFILEname) != true)
      {
        //이 파일은 존재하지 않는 것이므로 열어서는 안된다.
        return(false);

      }

  //}


  //-------------------------------------
  //file 이 존재 하는 것이므로 열어준다.
  //-------------------------------------


  //[Push]
  //{
      //새로운 파일을 열어야 하므로 현재 처리 중인 [파일정보/parser 정보] 를
      //대피시켜준다. parserinfo 구조체 설명을 참고한다.
      if(PARSERINFOSTACK_Push(&parserinfo) != true)
      {
        return(false);

      }

  //}

  //[filename]
  //{
      //모든 file 정보는 fileinfo 구조체에 저장해야 하므로 일단 이름을 저장.
      STR_Assign(fileinfo.name, pFILEname);

  //}


  lbFileProc: //[2012.05.27.일][추가!!!]


  //[파일열기][순수하게 파일만 처리]
  //{
      //읽기 전용 모드로 파일을 연다.
      fileinfo.handle = FileOpen((AnsiString)fileinfo.name, fmOpenRead);
      //[2012.05.27.일][중요추가!!!]{------------
      //[문서접근] 오류시는 다시 처리.
      if(fileinfo.handle == -1) goto lbFileProc;
      //}----------------------------------------

      //파일의 크기를 얻는다.
      //파일 끝으로 포인터를 이동하여 위치를 얻는데 이것이 크기가 된다.
      fileinfo.size = FileSeek(fileinfo.handle, 0, 2);
      //[2012.05.27.일][중요추가!!!]{----------
      //[문서접근] 오류시는 다시 처리.
      if(fileinfo.size == -1) goto lbFileProc;
      //}--------------------------------------

      //[!]{-----------------------------------------------------
      //포인터를 다시 파일의 처음으로 돌려 놓는다.
      //[2012.05.27.일][중요추가!!!]{----------------------------
      //[문서접근] 오류시는 다시 처리.
      if(FileSeek(fileinfo.handle, 0, 0) == -1) goto lbFileProc;
      //}--------------------------------------------------------

      //새로운 파일을 저장하기 위하여 이전 파일 저장 공간을 삭제한다.
      if(fileinfo.buf != NULL) { delete [] fileinfo.buf; fileinfo.buf = NULL;}

      //파일 크기에 맞도록 버퍼를 생성한다.
      //fileinfo.buf = new char[fileinfo.size];
      //[동적생성단위적용][2021.01.24.일][수정]
      fileinfo.buf = new char[UnitX(1024, fileinfo.size)];

      //파일을 버퍼로 읽어 들인다.
      FileRead(fileinfo.handle, fileinfo.buf, fileinfo.size);

      //파일을 닫아준다.
      FileClose(fileinfo.handle);

  //}

  //[filelist 정보 추가]
  //{
      //parserinfo 에서 filelistindex 를 할당 받으므로 반드시 이보다 먼저
      //처리해 주어야 한다. 필요한 정보는 file 을 open 하면서 이미 모두 얻었다.

      if(FILELIST_Add(fileinfo.name, fileinfo.size) != true)
      {
        return(false);

      }

  //}

  //[parserinfo 정보 추가]
  //{
      //[초기화]{-------------------------------------------------------
      //이미 parserinfo 는 push 한 상태이므로 새로운 파일에 맞게 완전히
      //초기화 한다.
      PARSERINFO_Format(&parserinfo);
      //}---------------------------------------------------------------

      //[정보처리]
      //{
          //초기화로 기본값은 들어 있으므로 추가 정보를 저장한다.

          //file[] 이 저장된 buffer 를 넘겨준다.
          //이는 새로 파일을 열면서 동적으로 새로 생성되므로 반드시 새로 할당한다.
          parserinfo.buf      = fileinfo.buf;

          //filelist[] 상에서 현재 새로 연 filename 의 index 를 찾아서 할당한다.
          FILELIST_GetIndex_WithName(fileinfo.name, &(parserinfo.filelistindex));

          //[2005.10.07.금][추가!!!]
          //{
              //size 정보도 추가한다.
              //위에서 이미 얻어진 fileinfo.size 값을 직접 할당해 주어도 된다.
              if(FILELIST_GetSize_WithIndex(parserinfo.filelistindex, &(parserinfo.filesize)) == false)
              {
                //함수 error!!!
                //파일을 열지 않아야 한다.
                return(false);

              }

          //}

          //[check]
          //{
              if(parserinfo.filelistindex == -1)
              {
                //-1 이라면 찾는 파일이 존재하지 않는 것이다.
                return(false);

              }

          //}

      //}

  //}

  //여기까지 온것은 아무 이상이 없는 것이다.
  return(true);

}

bool __fastcall DATABASE::FILE_Call_Exit(void)
{
  //[2005.09.16.금][새로만듬!!!]{---------------------------------------------------
  //파일을 여는 것은 함수를 call 하는 것과 같이 처리 되므로 파일을 닫을때는
  //역시 이 파일 이전에 처리 하던 파일을 다시 열어 주고 해당 정보 초기화를
  //수행해 주어야 한다. (원래 파일의 parserinfo 정보를 다시 재 설정한다.)
  //
  //parserinfo 정보의 경우 다른 것은 이전에 대피한 값을 그대로 사용하면 되지만,
  //buf[] 는 새로 생성되므로 새로 할당해 주어야 한다.
  //
  //[주의!!!]
  //file 을 다시 열때도 역시 fileinfo 구조체에 일단 저장해 놓고 처리해야 한다.
  //
  //[2005.09.17.토][추가!!!][중요!!!]{----------------------------------------------
  //파일을 새로 열때 현재 처리한 파일이 가장 처음 소스 즉, main() 이 들어있는
  //소스인 경우는 pop() 하는 경우 filename 이 "GIGYEIN" 이 된다.
  //이 경우는 처리할 파일이 더이상 존재하지 않는 것이므로 파일을 열지 않고
  //바로 종료해야 한다. 그러나 결과는 true 로 해석한다.
  //단, 이 경우는 이 함수 사용후 더이상 처리할 파일이 존재하지 않으므로
  //바로 parser 를 종료해야 한다.
  //
  //[2012.05.27.일][중요수정!!!]----------------------------------------------------
  //<FileOpen()>, <FileSeek()> API 는 오류 발생시 <-1> 를 반환한다.
  //
  //처리하는 문서들과 같은 하드디스크안의 [동영상 재생] 시 이 문서들에 빈번하게
  //접근하는 경우 [오류] 가 발생하며 <-1> 을 반환한다.
  //
  //이는 [실시간 선언 정보판] 을 확인하다 간혹 [오류] 가 발생하는 원인을 추적중
  //알아낸 것으로 <Parser()> 시 <include> 된 문서등 API 가 많은 경우 <함수묶음.h>
  //문서를 수십번을 열고 닫기 하게 되는데 이때 [빈도] 가 높은 탐색이 간혹 [오류] 가
  //발생하고 <-1> 을 반환한다.
  //
  //물리적인 디스크에 여러개의 동시 작업 하는 [문서] 가 존재하는 경우 접근오류임을
  //발견하였다.
  //
  //이는 거의 1회만 발생하는 것으로 간단하게 다시 처리하는 것으로 처리하였다.
  //아무 이상없이 잘 된다.
  //}-------------------------------------------------------------------------------

  //[delete]{-----------------------------------------------------------------
  //먼저 현재 처리를 끝낸 파일이 들어있는 buf[] 를 memory 에서 해제시킨다.
  //이 정보는 parserinfo.buf[] 에도 동일하게 저장되 있으나 주가 되는
  //fileinfo.buf[] 를 대상으로 하는 것이 좋다.(결과는 같으니까)
  //if(fileinfo.buf != NULL) { delete [] fileinfo.buf; fileinfo.buf = NULL; }
  //}-------------------------------------------------------------------------

  //[pop]{---------------------------------------------------------------
  //먼저 push() 한 이전 정보를 다시 pop() 해 온다.
  //현재 parserinfo.buf[] 에 저장된 파일은 이미 위에서 fileinfo.buf[] 를
  //대상으로 삭제 되었으므로 여기서는 pop() 한 정보를 바로 현재 설정할
  //parserinfo 에 덮어쓰면 된다.
  if(PARSERINFOSTACK_Pop(&parserinfo) != true)
  {
    return(false);

  }
  //}--------------------------------------------------------------------

  //[fileinfo]
  //{
      //file 을 열기 위하여 fileinfo 정보를 만들어 준다.

      //[format]{--------------------------------------------
      //일단 새로운 설정을 위하여 기존의 정보를 format 한다.
      FILEINFO_Format(&fileinfo);
      //}----------------------------------------------------

      //[name]{-----------------------------------------------------------------------
      //이미 parserinfo.filelistindex 정보를 사용하여 해당 index 의
      //filename 을 알수 있다.
      if(FILELIST_GetName_WithIndex(parserinfo.filelistindex, fileinfo.name) != true)
      {
        return(false);

      }
      //}-----------------------------------------------------------------------------
  //}


  //[filename == "GIGYEIN" ?]
  //{
      //pop() 한 filename 이 "GIGYEIN" 이라면 더이상 처리할 파일이 없는
      //것이므로 여기서 true 로 종료해야 한다.
      if(STR_Match_NoCase(fileinfo.name, "GIGYEIN") == true)
      {
        //더이상 처리할 파일이 없으므로 여기서 바로 종료한다.
        return(true);

      }

      //여기까지 온것은 계속 처리할 파일이 있는 것이므로 file 을 열어준다.

  //}


  //[file 유/무 확인]
  //{
      //****************************************************
      //전달받은 file 이 존재 하는지 확인한다.
      if(FileExists((AnsiString)fileinfo.name) != true)
      {
        //이 파일은 존재하지 않는 것이므로 열어서는 안된다.
        return(false);

      }
      //}***************************************************
  //}

  //-------------------------------------
  //file 이 존재 하는 것이므로 열어준다.
  //-------------------------------------

  
  lbFileProc: //[2012.05.27.일][추가!!!]


  //[파일열기][순수하게 파일만 처리]
  //{
      //읽기 전용 모드로 파일을 연다.
      fileinfo.handle = FileOpen((AnsiString)fileinfo.name, fmOpenRead);
      //[2012.05.27.일][중요추가!!!]{------------
      //[문서접근] 오류시는 다시 처리.
      if(fileinfo.handle == -1) goto lbFileProc;
      //}----------------------------------------

      //파일의 크기를 얻는다.
      //파일 끝으로 포인터를 이동하여 위치를 얻는데 이것이 크기가 된다.
      fileinfo.size = FileSeek(fileinfo.handle, 0, 2);
      //[2012.05.27.일][중요추가!!!]{----------
      //[문서접근] 오류시는 다시 처리.
      if(fileinfo.size == -1) goto lbFileProc;
      //}--------------------------------------

      //[!]{-----------------------------------------------------
      //포인터를 다시 파일의 처음으로 돌려 놓는다.
      //[2012.05.27.일][중요추가!!!]{----------------------------
      //[문서접근] 오류시는 다시 처리.
      if(FileSeek(fileinfo.handle, 0, 0) == -1) goto lbFileProc;
      //}--------------------------------------------------------

      //새로운 파일을 저장하기 위하여 이전 파일 저장 공간을 삭제한다.
      if(fileinfo.buf != NULL) { delete [] fileinfo.buf; fileinfo.buf = NULL; }

      //파일 크기에 맞도록 버퍼를 생성한다.
      //fileinfo.buf = new char[fileinfo.size];
      //[동적생성단위적용][2021.01.24.일][수정]
      fileinfo.buf = new char[UnitX(1024, fileinfo.size)];

      //파일을 버퍼로 읽어 들인다.
      FileRead(fileinfo.handle, fileinfo.buf, fileinfo.size);

      //파일을 닫아준다.
      FileClose(fileinfo.handle);
  //}

  //[parserinfo 정보 추가]
  //{
      //[정보처리]{-----------------------------------------------
      //이미 pop() 함수로 이전에 대피한 값으로 설정 된 상태이므로
      //새로 생성된 buf[] 의 정보만 할당해 주면 된다.
      parserinfo.buf           = fileinfo.buf;
      //}---------------------------------------------------------
  //}
  
  //여기까지 온것은 아무 이상이 없는 것이다.
  return(true);

}

bool __fastcall DATABASE::FILE_Save(char         *pFILEname,
                                    void         *pBUF,
                                    unsigned int  pBUFsize)
{
  //[2005.09.13.화][생성!!!]{------------------------------------------------
  //전달받은 buf[] 의 내용을 지정 size 만큼 지정 filename 으로 저장한다.
  //pFILEName 에는 경로와 확장자까지 모두 포함하고 있어야 한다.
  //이 함수는 전용이 아닌 일반적인 용도로 범용으로 여러 곳에서 사용될수있다.
  //}------------------------------------------------------------------------


  //[VAR]
  //{
      //{------------------------------------
      //파일을 열기 위하여 사용하는 두 정보.
      AnsiString  filename;
      int         filehandle;
      //}------------------------------------
  //}


  //filename 을 만든다.
  filename = (AnsiString)pFILEname;

  //pBUF[] 의 내용을 저장할 파일을 하나 만든다.
  filehandle = FileCreate(filename);

  //[파일 생성 확인]
  //{
      //파일이 생성되었는지 존재유무를 확인한다.
      if(FileExists(filename) != true)
      {
        //파일이 생성되지 않아 존재하지 않는 것이므로 error!
        return(false);

      }
  //}

  //[추가의 경우]
  //{
      //파일을 [쓰기모드] 로 연다.
      //filehandle = FileOpen(filename, fmOpenWrite);

      //파일 끝에부터 추가를 해야 하므로 파일 끝으로 이동한다.
      //FileSeek(filehandle, 0, 2 /*또는 soFromEnd*/);
  //}

  //[파일 내용 추가]
  //{
      if(pBUF != NULL)
      {
        //파일 끝에 pBUF[] 의 내용을 pBUFsize 만큼 추가한다.
        FileWrite(filehandle, pBUF, pBUFsize);

        //파일을 닫는다.
        FileClose(filehandle);

      }

  //}

  //여기까지 온것은 아무 이상없이 파일로 저장된 것이다.
  return(true);

}

//----------------------------------------------------------------------------------
//[실시간 선언 정보판(연산자) 관련]-------------------------------------------------
//----------------------------------------------------------------------------------

void __fastcall DATABASE::RtExpMark_Init(void)
{
  //[2012.06.19.화][생성!!!]{---
  //[2012.06.21.목][추가!!!]----
  //[2012.06.23.토][추가!!!]----
  //}---------------------------

  //처음 저장 위치 지정.
  _rtExpMark.sp = 0;

  //처음에는 찾지 않는것으로 초기화.
  _rtExpMark.opIndex = -1;

  //[2012.06.23.토][추가!!!]
  _rtExpMark.opLength = 0;

  //처음에는 처리 금지.
  _rtExpMark.on = false;

  //[2012.06.21.목][추가!!!]
  //처음에는 찾는 것이 없는것으로 설정.
  _rtExpMark.motherTypeListIndex = -1;

  //처음에는 [전역영역] 인 것으로 설정.
  _rtExpMark.funcRecIndex = -1;

}

void __fastcall DATABASE::RtExpMark_Reset(void)
{
  //[2012.06.23.토][생성!!!]{----------------------------------------------
  //다른 정보는 그대로 두고 <sp> 만 초기화 한다.
  //즉, 내용을 비우고 첫 항목을 설정.
  //
  //[함수영역] 의 시작이나 [지역변수 선언영역 끝] 에서 초기화 된다.
  //<_rtDefInfoEtc.localDefEndIndex> 위치가 정해질때는 반드시 이 함수로
  //초기화 하고 <_rtDefInfoEtc.localDefEndIndex> 위치를 처음 항목 위치로
  //기록하게 된다.
  //
  //즉, [함수] 영역에서 첫 [식] 의 위치는 <_rtDefInfoEtc.localDefEndIndex>
  //위치가 된다.
  //}----------------------------------------------------------------------

  //처음 저장 위치 지정.
  _rtExpMark.sp = 0;

}

void __fastcall DATABASE::RtExpMark_Push(int  pIndex)
{
  //[2012.06.19.화][생성!!!]{---
  //[2012.06.20.수][수정!!!]----
  //"(" 인 경우만 사용된다.
  //}---------------------------

  //[동작 상태인가?]
  //{
      //[!]{-----------------------
      //동작이 허가된 상태만 처리.
      //}--------------------------

      if(_rtExpMark.on != true) return;

  //}

  //[동작 정지 조건 인가?]
  //{
      //[!]{----------------------------------------------------------------
      //[연산자] 위치를 넘는 경우는 원하는 것을 찾은 것으로 보고 동작 정지.
      //}-------------------------------------------------------------------

      if(_rtExpMark.opIndex <= pIndex) { _rtExpMark.on = false; return; }

  //}

  //[처리 가능 확인]
  //{
      //용량을 넘는 경우는 처리하지 않는다.
      if(_rtExpMark.sp >= d_RTEXPMARK_Max) return;

  //}

  _rtExpMark.index[_rtExpMark.sp] = pIndex;

  //다음 저장 위치 지정.
  _rtExpMark.sp++;

}

void __fastcall DATABASE::RtExpMark_Pop(//[2012.06.21.목][추가!!!]
                                        int  pIndex)
{
  //[2012.06.19.화][생성!!!]{-------------------------------------
  //실제는 읽어서 버린다.
  //
  //[2012.06.20.수][수정!!!]--------------------------------------
  //")" 인 경우만 사용된다.
  //
  //[2012.06.21.목][수정!!!]--------------------------------------
  // " ; ... 함수(구조체.구성원); " 인 경우
  //")" 에서 <Pop()> 을 해 버리면 "(" 위치가 찾고자 하는 위치인데
  //"(" 가 해제돼 버리고 ";" 에서 <_rtExpMark.on:false> 가 되면
  //결국 가장 처음의 ";" 위치가 찾는 위치가 되고 만다.
  //
  //따라서, ")" 에서 <Pop()> 을 처리시에도 <index> 를 전달 받아서
  //<index> 가 <_rtExpMark.opIndex> 보다 큰 경우는 여기서도
  //<_rtExpMark.on:false> 를 처리할수 있어야 한다.
  //
  //즉, <Pop()> 시에도 [동작정지] 처리를 해야 한다는 것.
  //그래야 원하는 "(" 위치가 남게 된다.
  //
  //어제 이 문제를 발견하고 금일 수정한다.
  //}--------------------------------------------------------------

  //[동작 상태인가?]
  //{
      //[!]{-----------------------
      //동작이 허가된 상태만 처리.
      //}--------------------------

      if(_rtExpMark.on != true) return;

  //}

  //[동작 정지 조건 인가?]
  //{
      //[2012.06.21.목][추가!!!]{-------------------------------------------
      //[연산자] 위치를 넘는 경우는 원하는 것을 찾은 것으로 보고 동작 정지.
      //}-------------------------------------------------------------------

      if(_rtExpMark.opIndex <= pIndex) { _rtExpMark.on = false; return; }

  //}

  //[처리 가능 확인]
  //{
      //용량을 넘는 경우는 처리하지 않는다.
      if(_rtExpMark.sp <= 0) return;

  //}

  //저장 위치를 이전으로 수정하는 것 외에 처리할 것은 없다.
  _rtExpMark.sp--;

}

void __fastcall DATABASE::RtExpMark_Write(int  pIndex)
{
  //[2012.06.19.화][생성!!!]{--------------------------------------
  //마지막에 기록한 값을 새것으로 교체.
  //
  //[2012.06.20.수][수정!!!]---------------------------------------
  //[문장묶음/문장] 처리부에서 반드시 "{ }" 등이 오는 것이 아니고
  //처음부터 ";" 가 먼저 올수 있는데 이 경우는 <Push()> 된 항목이
  //없기 때문에 [재기록] 할수 있는 대상이 없다.
  //따라서, 아직 항목이 한개도 추가된 것이 없는 경우는 [재기록] 이
  //아니라 <Push()> 하는 것으로 수정한다.
  //}--------------------------------------------------------------

  //[동작 상태인가?]
  //{
      //[!]{-----------------------
      //동작이 허가된 상태만 처리.
      //}--------------------------

      if(_rtExpMark.on != true) return;

  //}

  //[동작 정지 조건 인가?]
  //{
      //[!]{----------------------------------------------------------------
      //[연산자] 위치를 넘는 경우는 원하는 것을 찾은 것으로 보고 동작 정지.
      //}-------------------------------------------------------------------

      if(_rtExpMark.opIndex <= pIndex) { _rtExpMark.on = false;  return; }

  //}

  //[현재 항목이 하나도 없나?]
  //{
      //[2012.06.20.수][추가!!!]{--------------------------------
      //현재 [항목] 이 한개도 없는 경우는 [재기록] 할수 없으므로
      //[항목] 을 <Push()> 로 한개 추가한다.
      //}--------------------------------------------------------

      if(_rtExpMark.sp == 0)
      {
        //[!]{------------------------------------------------
        //현재 [항목] 이 한개도 없는 경우는 <Push()> 로 처리.
        //}---------------------------------------------------

        //[처리 가능 확인]
        //{
            //용량을 넘는 경우는 처리하지 않는다.
            if(_rtExpMark.sp >= d_RTEXPMARK_Max) return;

        //}

        _rtExpMark.index[_rtExpMark.sp] = pIndex;

        //다음 저장 위치 지정.
        _rtExpMark.sp++;

      }
      else
      {
        //[처리 가능 확인]
        //{
            //용량을 넘는 경우는 처리하지 않는다.
            if(!((0 < _rtExpMark.sp) && (_rtExpMark.sp <= d_RTEXPMARK_Max))) return;

        //}

        //<sp> 는 항상 [다음 저장 위치] 를 가지기 때문에 <-1> 한 위치가
        //마지막에 저장한 값의 위치.
        _rtExpMark.index[_rtExpMark.sp - 1] = pIndex;

      }

  //}

}

int __fastcall DATABASE::RtExpMark_Read(void)
{
  //[2012.06.19.화][생성!!!]{------------
  //마지막에 기록한 값을 읽어서 반환.
  //
  //범위를 초과한 경우는 <-1> 반환.
  //
  //[주의!!!]----------------------------
  //이 함수는 항상 [동작가능] 해야 한다.
  //}------------------------------------

  //[처리 가능 확인]
  //{
      //용량을 넘는 경우는 <-1> 로 상태를 알려준다.
      if(!((0 < _rtExpMark.sp) && (_rtExpMark.sp <= d_RTEXPMARK_Max))) return(-1);

  //}

  //<sp> 는 항상 다음 저장 위치를 가지기 때문에 <-1> 한 위치가
  //마지막에 저장한 값의 위치.
  return(_rtExpMark.index[_rtExpMark.sp - 1]);

}

void __fastcall DATABASE::RtExpMark_OperatorIndex(int  pIndex)
{
  //[2012.06.19.화][생성!!!]{-----------------------------------
  //<_rtExpMarkOperatorIndex> 값 설정.
  //
  //"->" 나 "." 연산자의 시작 위치가 된다.
  //이 [연산자] 를 포함하는 [식] 의 시작위치를 찾는데 필요.
  //
  //[주의!!!]---------------------------------------------------
  //내부적으로 해당 [정보 구조체] 를 초기화 한다.
  //유일하게 설정하는 곳으로 여기서 한번에 처리하는 것이 좋다.
  //
  //[설명!!!]---------------------------------------------------
  //이 함수는 <Ctrl+Space> 를 처리하는 함수에서 [연산자] 위치를
  //지정하는데 한번 사용된다.
  //}-----------------------------------------------------------

  //[정보 구조체:초기화]
  //{
      //[유일하게] 설정하는 부분이므로 여기서 직접 한번 초기화 한다.
      RtExpMark_Init();

  //}

  //[연산자 위치 설정]
  //{
      //[!]{-----------------------------
      //<-1> 이 아닌 유효한 경우만 처리.
      //}--------------------------------

      if(pIndex >= 0)
      {
        _rtExpMark.opIndex = pIndex;

        //정보 수집 동작 상태로 설정.
        _rtExpMark.on      = true;

      }

  //}

}

//----------------------------------------------------------------------------------
//[기타 처리 관련]------------------------------------------------------------------
//----------------------------------------------------------------------------------

//[DEBUG]{------------------------------------
//내부적으로 debug 를 위한 함수들을 배치한다.
//개발시 내용을 확인해 보기 위한 함수들.
//실제로 parser 에서 사용되지는 않는다.
//}-------------------------------------------


void __fastcall DATABASE::DEBUG_Database_View(void)
{
  //[2005.09.06.화][생성!!!]{-------------------------------------------------------
  //{DATABASE} 안의 각각의 정보[] 들의 내용을 문자열로 만들어서 쉽게 내용을
  //확인해 볼수 있도록 한다.
  //일단, 문자열로 정리한 다음에 한꺼번에 "DATABASE.txt" 파일로 현재 [program 경로]
  //에 저장한다.
  //
  //[2005.09.14.수][대폭수정!!!]----------------------------------------------------
  //이전과 달리 AnsiString 을 사용하지 않고 새로만든 [STRBUF 구조체] 를
  //사용하여 처리한다. 처리 속도가 매우 빠르다.
  //추가할 정보는 얼마든지 추가 가능하다.
  //
  //[2009.01.28.수][수정!!!]--------------------------------------------------------
  //이전과 달리 {DATABASE} 의 전용 지정 경로에 문서를 만들어 준다.
  //이는 <*.gprj> 경로의 [debug] 폴더가 해당되며, <Build> 후 자동으로 생성된다.
  //
  //[2012.04.20-1.목][수정!!!]------------------------------------------------------
  //}-------------------------------------------------------------------------------

  //[2007.07.20.금][수정있음!!!]


  //[VAR]
  //{
      //[file-save 를 위한 구조체정보]
      //{
          //중간에 처리되는 모든 문자열을 이곳에 저장한다.
          struct  STRBUF  strbuf;

          //[2009.01.28.수][수정!!!]
          char    debugFileName[OPT_debugPath_length];
          char    fileName[OPT_lineStrSize];

      //}

      int         i, j;

      char        tempStr[OPT_lineStrSize];

  //}

  //[초기화]
  //{
      //[2012.04.29.일][추가!!!]{---------------------------------
      //[STRBUF] 는 사용전 반드시 한번만 처음 사용 상태로 만든다.
      //}---------------------------------------------------------

      STRBUF_FirstInit(&strbuf);

  //}

  //[공간 생성]
  //{
      //[!]{------------------------------------------------------------------------------
      //STRBUF.buf[] 를 생성한다.
      //{DATABASE} 용량에 따라 크기를 정해야 하나, 일단 1 Mbyte 정도로 넉넉하게 설정한다.
      //}---------------------------------------------------------------------------------

      STRBUF_New(&strbuf, OPT_databaseviewbuf_size);

  //}

  //[record]
  //{
      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< record[] >\r\n");

          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      //[목록추가]
      //{
          STRBUF_Add(&strbuf, "[num]\tname\t\tix\tkind\tarea\tti\tfi\tp\tmi\tsz\t\tofs\t\tad\tasz\r\n\r\n");

      //}

      //[!]{-----------------------------------
      //가장 먼저 {DATABASE} 의 것을 정리한다.
      //현재 까지 저장된 것 까지만 처리한다.
      //}--------------------------------------

      for(i=0; i<record_count; i++)
      {
        //[record-number 를 기록한다]
        //{
            STRBUF_Add(&strbuf, "[");
            STRBUF_Add(&strbuf, ((AnsiString)IntToStr(i)).c_str());
            STRBUF_Add(&strbuf, "]");
            STRBUF_Add(&strbuf, "\t");

        //}

        if(record[i].name != NULL)
        {
          STRBUF_Add(&strbuf, record[i].name);                           STRBUF_Add(&strbuf, "\t\t");

        }

        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].index)).c_str());          STRBUF_Add(&strbuf, "\t");

        //상수 값으로는 구분이 쉽지 않으므로 문자열이나 간단한 기호로 표시될수 있게 만든다.
		STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].kind)).c_str());           STRBUF_Add(&strbuf, "\t");

		STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].area)).c_str());  STRBUF_Add(&strbuf, "\t");
		STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].typelistindex)).c_str());  STRBUF_Add(&strbuf, "\t");
		STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].filelistindex)).c_str());  STRBUF_Add(&strbuf, "\t");
		STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].pointer)).c_str());        STRBUF_Add(&strbuf, "\t");
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].motherindex)).c_str());    STRBUF_Add(&strbuf, "\t");

        //[추가 정보 처리]
        //{
            //[2008.11.06.목][추가!!!]

            //[size]
            CONV_LongVal_To_Hex2(record[i].size, tempStr);
            STRBUF_Add(&strbuf, "0x");  STRBUF_Add(&strbuf, tempStr);  STRBUF_Add(&strbuf, "\t\t");

            //[address]
            CONV_LongVal_To_Hex2(record[i].address, tempStr);
            STRBUF_Add(&strbuf, "0x");  STRBUF_Add(&strbuf, tempStr);  STRBUF_Add(&strbuf, "\t\t");

        //}

        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].arraydimension)).c_str()); STRBUF_Add(&strbuf, "\t");

        //[배열 차원 크기 정보]
        //{
            //NULL 이 아닌 경우는 arraydimension 을 참고해서 각각의 크기를 [a][b][c]...
            //처럼 문자열로 만들어 표시해 준다.

            if((record[i].arraydimension != 0) && (record[i].arraysize != NULL))
            {
              //array 가 최소 1 차원은 되므로 각각의 size 를 문자열로 만들어 준다.
              for(j=0; j<record[i].arraydimension; j++)
              {
                //"[A][B][C]" 의 형식으로 차원의 크기를 알려주는 문자열이 만들어진다.
                STRBUF_Add(&strbuf, "[");
                STRBUF_Add(&strbuf, ((AnsiString)IntToStr(record[i].arraysize[j])).c_str());
                STRBUF_Add(&strbuf, "]");

              }

            }

        //}

        //[문자열 정보]
        //{
            //[2006.01.26.목][추가!!!]{---------------------------
            //record 의 마지막 부가 정보인 문자열정보를 추가한다.
            //}---------------------------------------------------

            //[2012.04.20-1.목][주석처리!!!]
            /*if(record[i].str_mem != NULL)
            {
              STRBUF_Add(&strbuf, record[i].str_mem);

            }*/

            //[STRHEAP] 방식으로 변경.
            //문자열이 있는 경우만 추가.
            if(record[i].str_mem != -1)
            {
              STRBUF_Add(&strbuf, STRHEAP_Str_Ptr(&_strHeap, record[i].str_mem));

            }

        //}

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[기타정보(각종 LIST[] 들)] 를 순서대로 문자열로 바꾸어 준다.

  //[filelist]
  //{
      //[2012.04.07.토][추가!!!]


      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< filelist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

          //[2012.04.07.토][수정!!!]
          //<includeListTotal[]> 정보 추가로 2=>3 행으로 표기.
          STRBUF_Add(&strbuf, "한개 정보당 3 행을 사용.\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      //문자열이 길므로 2열로 배치한다.

      //현재 까지 저장된 것 까지만 처리한다.
      for(i=0; i<filelist_count; i++)
      {
        //name 을 윗행에 배치한다.
        STRBUF_Add(&strbuf, filelist[i].name);

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

        //size 정보를 배치한다.
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(filelist[i].size)).c_str());
        STRBUF_Add(&strbuf, "\t:\t");

        //include_list[] 정보를 깔아준다.
        for(j=0; j<filelist[i].include_list_count; j++)
        {
          STRBUF_Add(&strbuf, ((AnsiString)IntToStr(filelist[i].include_list[j])).c_str());
          STRBUF_Add(&strbuf, "\t");

        }

        //[2012.04.07.토][추가!!!]
        //{
            //다음행으로 넘긴다.
            STRBUF_Add(&strbuf, "\r\n"); //CRLF

            STRBUF_Add(&strbuf, "(");
            STRBUF_Add(&strbuf, ((AnsiString)IntToStr(i)).c_str());
            STRBUF_Add(&strbuf, ")\t:\t");

            //includeListTotal[] 정보를 깔아준다.
            for(j = 0; j < filelist[i].includeListTotalCount; j++)
            {
              STRBUF_Add(&strbuf, ((AnsiString)IntToStr(filelist[i].includeListTotal[j])).c_str());
              STRBUF_Add(&strbuf, "\t");

            }

        //}

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[typelist]
  //{
      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< typelist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      //현재 까지 저장된 것 까지만 처리한다.
      for(i = 0; i < typelist_count; i++)
      {
        //[record-number 기록]
        //{
            STRBUF_Add(&strbuf, "[");
            STRBUF_Add(&strbuf, ((AnsiString)IntToStr(i)).c_str());
            STRBUF_Add(&strbuf, "]");
            STRBUF_Add(&strbuf, "\t");

        //}

        //[표시]
        //{
            //정리된 문자열 한줄을 추가한다.
            STRBUF_Add(&strbuf, typelist[i].type);
			STRBUF_Add(&strbuf, "\t");
			STRBUF_Add(&strbuf, ((AnsiString)IntToStr(typelist[i].rec_index)).c_str());

            //[2007.07.20.금][추가!!!]
            //{
                //size 정보도 보여준다.
                STRBUF_Add(&strbuf, "\t");
                STRBUF_Add(&strbuf, ((AnsiString)IntToStr(typelist[i].size)).c_str());

            //}

        //}

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[definelist]
  //{
      //[2005.10.17.월][추가!!!]

      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< definelist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      //[목록추가]
      //{
          STRBUF_Add(&strbuf, "[num]\tname\t\tix\tfi\tstr\r\n\r\n");

      //}

      //현재 까지 저장된 것 까지만 처리한다.
      for(i=0; i<definelist_count; i++)
      {
        //[record-number 기록]
        //{
            STRBUF_Add(&strbuf, "[");
            STRBUF_Add(&strbuf, ((AnsiString)IntToStr(i)).c_str());
            STRBUF_Add(&strbuf, "]");
            STRBUF_Add(&strbuf, "\t");

        //}

        //[문자열 추가]
        //{
            //정리된 문자열 한줄을 추가한다.
			STRBUF_Add(&strbuf, definelist[i].defname);                                        STRBUF_Add(&strbuf, "\t\t");
			STRBUF_Add(&strbuf, ((AnsiString)IntToStr(definelist[i].index)).c_str());          STRBUF_Add(&strbuf, "\t");
			STRBUF_Add(&strbuf, ((AnsiString)IntToStr(definelist[i].filelistindex)).c_str());  STRBUF_Add(&strbuf, "\t");
			STRBUF_Add(&strbuf, definelist[i].defstr);                                         STRBUF_Add(&strbuf, "\t");

        //}

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[uselabellist]
  //{
      //[2006.02.15.수][추가!!!]

      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< uselabellist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      //[목록추가]
      //{
          STRBUF_Add(&strbuf, "[num]\tname\t\tfi\tarea\r\n\r\n");

      //}

      //현재 까지 저장된 것 까지만 처리한다.
      for(i=0; i<uselabellist_count; i++)
      {
        //[record-number 기록]
        //{
            STRBUF_Add(&strbuf, "[");
            STRBUF_Add(&strbuf, ((AnsiString)IntToStr(i)).c_str());
            STRBUF_Add(&strbuf, "]");
            STRBUF_Add(&strbuf, "\t");

        //}

        //[문자열 추가]
        //{
            //정리된 문자열 한줄을 추가한다.
			STRBUF_Add(&strbuf, uselabellist[i].name);                                          STRBUF_Add(&strbuf, "\t\t");
			STRBUF_Add(&strbuf, ((AnsiString)IntToStr(uselabellist[i].filelistindex)).c_str()); STRBUF_Add(&strbuf, "\t");
            STRBUF_Add(&strbuf, ((AnsiString)IntToStr(uselabellist[i].area)).c_str());          STRBUF_Add(&strbuf, "\t");

        //}

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[stringlist]
  //{
      //[2009.01.30.금][수정!!!]{------------------------------------------
      //전부 함수 단위로 처리되므로 표시 할 것이 없으므로 사용하지 않는다.
      //이왕 만들어 놓은 것이므로 주석으로 처리해 놓는다.
      //}------------------------------------------------------------------

      /*

      //[2006.06.04.일][추가!!!]

      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< stringlist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      //전체가 하나의 문자열로 되있으므로 그냥 문자열 전체를 추가하면 된다.

      //[record-number 기록]
      //{
          STRBUF_Add(&strbuf, stringlist.strbuf.buf);

      //}

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

      */

  //}

  //[keywordlist]
  //{
      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< keywordlist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      for(i=0; i<OPT_keyword_list_size; )
      {
        //한 행에 8 개씩 표시해 준다.
        for(j=0; (j<8) && (i<OPT_keyword_list_size); j++, i++)
        {
          //정리된 문자열 한줄을 추가한다.
          STRBUF_Add(&strbuf, keywordlist[i].kw);
          STRBUF_Add(&strbuf, "\t");

        }

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[operatorlist]
  //{
      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< operatorlist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      for(i=0; i<OPT_operatorlist_size; )
      {
        //한 행에 16 개씩 표시해 준다.
        for(j=0; (j<16) && (i<OPT_operatorlist_size); j++, i++)
        {
          //정리된 문자열 한줄을 추가한다.
          STRBUF_Add(&strbuf, operatorlist[i].op);
          STRBUF_Add(&strbuf, "\t");

        }

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[signlist]
  //{
      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< signlist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      for(i=0; i<OPT_signlist_size; )
      {
        //한 행에 16 개씩 표시해 준다.
        for(j=0; (j<16) && (i<OPT_signlist_size); j++, i++)
        {
          //정리된 문자열 한줄을 추가한다.
          STRBUF_Add(&strbuf, signlist[i].sign);
          STRBUF_Add(&strbuf, "\t");

        }

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[escapelist]
  //{
      //[제목추가]
      //{
          STRBUF_Add(&strbuf, "< escapelist[] >\r\n");
          STRBUF_Add(&strbuf, "\r\n"); //CRLF

      //}

      for(i=0; i<OPT_escapelist_size; )
      {
        //한 행에 16 개씩 표시해 준다.
        for(j=0; (j<16) && (i<OPT_escapelist_size); j++, i++)
        {
          //정리된 문자열 한줄을 추가한다.
          STRBUF_Add(&strbuf, escapelist[i].escape);
          STRBUF_Add(&strbuf, "\t");

        }

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }

      //빈줄을 하나 넣어준다.
      STRBUF_Add(&strbuf, "\r\n"); //CRLF

  //}

  //[파일로 저장]
  //{
      //[filename 만들기]
      //{
          //해당 program 실행 경로 안의 [Debug] 폴더에 <*.gprj> 와 같은 이름의 <*.txt> 문서로 저장된다.

          //[이름 만들기]
          //{
              STR_GetFileNameOnly(projectname, fileName);

              STR_Assign(tempStr, debugPath);
              STR_Add_AB(tempStr, tempStr, fileName);

              //확장자는 <*.txt> 로 만든다.
              STR_ChangeFileExt(tempStr, "gdb", debugFileName);

          //}

      //}

      //[저장]
      //{
          //처리된 만큼만 저장하면 되므로 strbuf.count-1 를 filesize 로 사용한다.
          //STRBUF.buf[] 는 문자열을 저장하므로 끝에 '\0' 까지가 count 에 포함되므로,
          //파일로 저장시에는 이 '\0' 은 제외 해 주어야 한다.

          FILE_Save(debugFileName, strbuf.buf, strbuf.count-1);

      //}

  //}

  //[저장소 삭제]
  //{
      //생성된 STRBUF.buf[] 를 삭제한다.
      STRBUF_Delete(&strbuf);

  //}

  return;

}

//------------------------------------------------------------------------------
//[STRHEAPCONF]-----------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall DATABASE::StrHeapConf_Init(void)
{
  //[2012.05.17.목][생성!!!]{--------------------------------------
  //<_strHeap_Conf> 공용 [비교 단어] 를 채워준다.
  //
  //모든 내용을 항상 사용하는 것이 아니라 영역 별로 지정하여 사용.
  //이곳에서는 일단 목록을 만들어 놓는것.
  //}--------------------------------------------------------------

  //[VAR
  //{
      int  i;

      int  shn;

      //[2012.05.16+2.금][추가!!!]
      int  count = 0;

  //}

  //[예약어]
  //{
      //[시작:위치] 지정.
      _strHeap_Conf_Keyword_s = count;

      for(i = 0; i < OPT_keyword_list_size; i++, count++)
      {
        shn = -1;
        STRHEAP_Str(&_strHeap_Conf, &shn, keywordlist[i].kw);

      }

      //[끝:위치] 지정.
      _strHeap_Conf_Keyword_e = count - 1;

  //}

  //[연산자]
  //{
      //[시작:위치] 지정.
      _strHeap_Conf_Operator_s = count;

      for(i = 0; i < OPT_operatorlist_size; i++, count++)
      {
        shn = -1;
        STRHEAP_Str(&_strHeap_Conf, &shn, operatorlist[i].op);

      }

      //[끝:위치] 지정.
      _strHeap_Conf_Operator_e = count - 1;

  //}

  //[기호]
  //{
      //[시작:위치] 지정.
      _strHeap_Conf_Sign_s = count;

      for(i = 0; i < OPT_signlist_size; i++, count++)
      {
        shn = -1;
        STRHEAP_Str(&_strHeap_Conf, &shn, signlist[i].sign);

      }

      //[끝:위치] 지정.
      _strHeap_Conf_Sign_e = count - 1;

  //}

  // ...

  //[구조체/공용체 이름 초기화]
  //{
      //마지막 가변 추가 정보는 <Parser()> 후에만 등록되므로
      //여기서는 범위를 초기화만 해 놓는다.
      _strHeap_Conf_Type_s = _strHeap_Conf_Sign_e + 1;
      _strHeap_Conf_Type_e = _strHeap_Conf_Type_s;

  //}

}

void __fastcall DATABASE::StrHeapConf_Type(void)
{
  //[2012.05.16+2.금][생성!!!]{-----------------------------------------------
  //<_strHeap_Conf> 공용 [비교 단어] 에 [구조체/공용체 선언이름] 을 넣는다.
  //
  //사용자가 직접 [선언] 한 것이라도 [형] 이므로 별도로 구분하기 위한것.
  //실제 [형식 적용] 대상이 된다.
  //
  //[주의!!!]-----------------------------------------------------------------
  //[구조체/공용체] 는 <Parser()> 를 처리해야 정리되므로 반드시 이를 확인.
  //
  //[중요!!!]-----------------------------------------------------------------
  //계속 추가되는 것이 아니라 자신의 영역안에서 [재기록] 하는 것으로 처리.
  //[STRHEAP] 은 자체적으로 같은 번호인 경우 이전것을 삭제하고 [재기록] 한다.
  //
  //그러므로, 다른 고정 [단어] 정보가 모두 정리된후 가장 [마지막] 에 추가.
  //}-------------------------------------------------------------------------

  //[VAR
  //{
      int  i;

      int  shn;

      //[2012.05.16+2.금][추가!!!]
      //순서대로 처리되고 가장 마지막에 추가되므로 <_strHeap_Conf_Sign_e>
      //다음 부터 추가횐다.
      int  count = _strHeap_Conf_Type_s;

  //}

  //[기존 항목 삭제]
  //{
      //[!]{----------------------------------------------------------------
      //<Parser()> 처리때마다 내용이 바뀔수 있으므로
      //기존 [단어] 는 삭제하고 새로 기록한다.
      //
      //순서대로 기록하고, [구조체/공용체] 정보는 가장 나중에
      //기록되므로 이가 빠진 곳 없이 [삭제] 한 부분부터 다시 사용할수 있다.
      //
      //지정 [목록] 이 [해제상태<-1>] 인 경우는 자동으로 [삭제] 처리를 하지
      //않기 때문에 이를 구분할 필요는 없다.
      //
      //즉, 지정 범위에 내용이 있다면 [삭제] 되고 <-1> 로 [해제] 상태라면
      //아무것도 처리하지 않는다.
      //}-------------------------------------------------------------------

      //단, [삭제] 의 내부 처리 구조상 [거꾸로] 처리하는 것이 좋다.
      for(i = _strHeap_Conf_Type_e; i >= _strHeap_Conf_Type_s; i--)
      {
        STRHEAP_Str_Delete(&_strHeap_Conf, i);

      }

  //}

  //[구조체/공용체 추가]
  //{
      //[!]{-------------------------------------------------------
      //[STRHEAP] 영역에서 이 부분은 항상 [고정정보] 저장부분 뒤로
      //이 시점에서는 항상 비워있으므로 순서대로 추가만 하면 된다.
      //}----------------------------------------------------------

      //[시작:위치] 지정.
      _strHeap_Conf_Type_s = count;

      //[C 언어형] 다음부터가 [구조체/공용체] 형이다.
      for(i = (c_type_last_typelistindex + 1); i < typelist_count; i++, count++)
      {
        //이미 삭제된 상태이므로 추가만 한다.
        shn = -1;
        STRHEAP_Str(&_strHeap_Conf, &shn, typelist[i].type);

      }

      //[끝:위치] 지정.
      _strHeap_Conf_Type_e = count - 1;

  //}

}

//------------------------------------------------------------------------------
//[EXP1OPERATOR]----------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall EXPDATABASE::Init(void)
{
  //[2006.03.21.화][수정!!!]{----------------
  //record[] 정보 전체를 완전히 초기화 한다.
  //}----------------------------------------


  //[VAR]
  //{
      int i;
  //}


  //[exprecord]
  //{
      //-----------------------------------------------------------------
      //count 값을 0 으로 초기화.
      recordcount = 0;

      for(i = 0; i < OPT_exprecord_size; i++)
      {
        //각각의 구조체 정보를 format 하는 것으로 전부 초기화 할수 있다.
        Format(&(record[i]));

      }
      //-----------------------------------------------------------------
  //}

  //[expoptrrecord]
  //{
      //--------------------------------------
      //count 값을 0 으로 초기화.
      expoptrrankcount = 0;

      for(i = 0; i < OPT_exprecord_size; i++)
      {
        OPTRRANK_Format(&(expoptrrank[i]));

      }
      //---------------------------------------
  //}

  return;

}

void __fastcall EXPDATABASE::Format(struct EXPRECORD *pRECORD)
{
  //[2006.03.21.화][생성!!!]{---------
  //지정된 구조체 정보를 format 한다.
  //
  //[0212.06.20.수][추가!!!]----------
  //}---------------------------------

  //[VAR]
  //{
      int  i = 0;

  //}

  pRECORD->Tdata_Fop     = true;  //기본적으로 [ data ] 로.
  pRECORD->word[0]       = '\0';  //NULL.
  pRECORD->kind          = 0;
  pRECORD->typelistindex = -1;
  pRECORD->pointer       = 0;

  //[2006.08.15.화][수정!!!]
  //{
      pRECORD->array         = 0;

      for(i = 0; i < 5; i++)
      {
        pRECORD->array_size[i] = 0;

      }

  //}

  //[2006.06.15.목][추가!!!]
  //{
      //{DATABASE} 의 <record-index> 값이므로 <-1> 로 초기화.
      pRECORD->recindex  = -1;

      pRECORD->_64bit_   = 0;
     
  //}

  //[2012.06.20.수][추가!!!]
  //[연산자] 의 [저장소] 상 [위치] 정보.
  pRECORD->wordIndex = -1;

}

bool __fastcall EXPDATABASE::Add(struct EXPRECORD *pRECORD)
{
  //[2006.03.22.수][생성!!!]{---------------
  //record[] 에 구조체정보를 하나 추가한다.
  //}---------------------------------------

  //[저장용량 확인!!!]
  //{
      //더이상 저장할수 없는 경우라면 error 가 된다.
      if(!(recordcount < OPT_exprecord_size))
      {
        //이 경우는 저장 한도를 넘어선 것이다.
        //아무 처리도 하지 않는다.
        return(false);

      }
  //}

  //[구조체 정보 추가!!!]
  //{
      record[recordcount] = (*pRECORD);
      recordcount++;
  //}

  //여기까지 온것은 ok!!!
  return(true);

}

bool __fastcall EXPDATABASE::Delete(int pDELETEindex)
{
  //[2006.04.17.월][생성!!!]{-------------------------------------------------
  //exprecord[] 에서 지정 행을 삭제 하고 빈곳을 뒤의 것을 당겨서 매꾸어 준다.
  //recordcount 개수도 수정해 주어야 한다.
  //동적으로 생성된 정보가 없으므로 그냥 다음 위치의 것을 지정된 위치로 copy
  //하는 것으로 지정 record 를 없앨수 있다.
  //}-------------------------------------------------------------------------


  //[VAR]
  //{
      int  i = 0;
  //}


  //[영역 check!!!]
  //{
      //지정된 index 가 해당 범위 안에 있는지 검사한다.
      if(!((0 <= pDELETEindex) && (pDELETEindex < recordcount)))
      {
        //지정 범위를 넘어선 것이므로 error!!!
        return(false);

      }
  //}


  for(i = pDELETEindex; i < (recordcount - 1); i++)
  {
    //뒤의것을 앞으로 copy 해 준다.
    record[i] = record[i + 1];

  }

  //한개의 record 가 삭제 되었으므로 recordcount 개수를 수정해 준다.
  recordcount--;

  //여기까지 온것은 이상 없는 것이다.
  return(true);


}

void __fastcall EXPDATABASE::OverWrite(int               pOVERWRITEindex,
                                       struct EXPRECORD *pRECORD)
{
  //[2006.04.29.토][생성!!!]{---------------------------------------
  //단순하게 지정된 index 위치에 전달받은 record 를 overwrite 한다.
  //}---------------------------------------------------------------

  record[pOVERWRITEindex] = (*pRECORD);
                                                       
  return;

}

bool __fastcall EXPDATABASE::SYMBOL_1ST_Data(class   DATABASE   *pDATABASE,
                                             struct  EXPRECORD  *pEXPrecord,
                                             char                rSYMBOL[])
{
  //[2007.07.13.금][생성!!!]{---------------------------------------------------------
  //EXPDATABASE::Data() 함수 안에서 사용되어 이미 선언되 있는 DATA 에 대하여 해당
  //[1차번역기호] 를 만들어 준다.
  //[1차번역기호] 는 <exprecord> 의 정보와는 달리 직접 ASM 에서 사용될수 있는 기호로
  //구성해 주어야 한다.

  //단, [식] 에서 [반환값 있는 함수] 가 사용된 경우는 [함수반환공간] 자체가 <temp> 가
  //되므로 이때는 별도 처리를 해주어야 한다.
  //}---------------------------------------------------------------------------------

  //[주의!!!]{-----------------------------------------------------------------------------------
  //EXPDATABASE::Data() 함수는 정보는 수집하는 별도의 TREE 가 있는 [상수] 나 [문자열] 은
  //처리하지 않으므로 이 함수도 [상수/문자열] 은 처리하지 않는다.
  //
  //[2007.07.14.토][수정!!!]---------------------------------------------------------------------
  //단, Data() 함수로 수집하는 DATA 는 이미 선언된것(G, L) 과 [식] 에서 사용된 [반환값있는 함수]
  //의 경우이다. 그러므로, EXPRESSION_MatchDataKind() 를 사용하여 종류를 구분하는 경우
  //matchDATAkind_constant 로 분류된 경우는 무조건 [반환값이 일반 변수인 함수] 로 보고 처리한다.
  //}--------------------------------------------------------------------------------------------

  //[VAR]
  //{
      //완성된 [1차번역기호] 를 저장한다.
      char  symbol[OPT_1st_symbol_length] = {""};

      //값을 16진수로 표기 변환시 사용한다.
      char  hexstr[OPT_1st_symbol_length] = {""};

      int   kind = 0;

      int   motherindex = 0;

      int   rec_kind = 0;

      int   rec_area = -1;

      //{tempdatabase} 에 자료를 저장하기 위한 temp-record 를 하나 만든다.
      struct TEMPRECORD  temprecord;

      //2008.10.15.수][추가!!!]
      //지금 처리 하는 DATA 가 순수 [구조체/공용체] 인 경우는 true 로 설정한다.
      bool   isStructOrUnion = false;

      //[2008.11.05.수][추가!!!]
      unsigned long long  rec_address;

  //}


  //[초기화]
  //{
      //일단 반환기호를 초기화 한다.
      STR_Assign(rSYMBOL, "");

      //[2008.11.01.토][추가!!!]{----------------------------------------------------
      //반드시 사용하기 전에 완전히 포맷을 해야 한다.
      //그렇지 않은 경우는 .org_typelistindex 가 초기화 되지 않아서 문제가 발생한다.
      _tempdatabase.Format(&temprecord);
      //}----------------------------------------------------------------------------

  //}

  //[종류구분]
  //{
      //<exprecord> 에 따른 DATA 의 종류를 구분한다.
      kind = EXPRESSION_MatchDataKind(pDATABASE, pEXPrecord);

  //}

  //[종류에따른처리]
  //{
      //[설명!!!]{-----------------------------------------------------------------------
      //DATA 종류를 구분하여 해당 기호를 만들어 준다.
      //기호는 한번에 완성하지 못하므로 단계별로 해당하는 것을 추가하는 방법을 사용한다.
      //
      //[주의!!!]------------------------------------------------------------------------
      //[2007.07.14.토][수정!!!]
      //matchDATAkind_constant 의 경우는 [반환값이 변수유형인 함수] 가 되므로
      //처리하지 않고 이 함수 뒷부분의 [함수] 처리부에서 처리되도록 그냥 둔다.
      //}--------------------------------------------------------------------------------

      //[구조체/공용체 구성원인지 확인]
      //{
          //[!]{------------------------------------------------------------------------
          //먼저 [구조체/공용체] 의 [구성원] 인지 확인한다.
          //이 경우는 어떤 종류라도 무조건 offset-address 자체가 되는 [상수값] 이 된다.
          //"(unsigned long)C.#.recindex" 의 형태로 만든다.
          //}---------------------------------------------------------------------------

          //if(pDATABASE->IS_Struct_Union_Member_withRECINDEX(pEXPrecord->recindex, &motherindex) != true)
          if(pDATABASE->REC_Field_Read2(pEXPrecord->recindex, _F_motherindex, NULL, &motherindex) != true)
          {
            //함수 자체의 error 인 경우다.
            return(false);

          }

      //}

      //[!]--------------------------------------------------------------------------------
      //[구조체/공용체] 의 [구성원] 여부에 따라서 처리.
      //[함수] 는 절대로 [구조체/공용체] 의 [구성원] 일수가 없으므로 신경쓰지 않아도 된다.
      //-----------------------------------------------------------------------------------

      if(motherindex > 0)
      {
        //[구성원]

        //[모체] 가 있으므로 이 경우는 [구성원] 에 해당한다.
        //단지 offset-address 를 나타내는 [주소값] 자체가 된다.

        //[추가주소처리]
        //{
            //[2008.11.05.수][수정!!!]{------------------------------------------------------------------
            //원래 이 위치에서 [구성원] 의 recindex 를 기록했으나 [구조체/공용체] 의 선언시 바로
            //해당 [구성원] 의 [추가주소] 를 얻는 것으로 금일 수정하였으므로 여기서도 바로 [추가주소] 를
            //사용하는 것으로 수정한다.
            //[2009.01.04.일][중요수정!!!]---------------------------------------------------------------
            //[구성원] 의 [추가주소] 는 결국 "." 나 "->" 여산자 에서 사용되는 [피연산자] 가 되므로
            //사용되는 [상수] 도 역시 C-Type 을 가져야 한다.
            //따라서, 1, 2, 4, 8 중 하나의 크기로 표시 되어야 한다.
            //이는 전용 [기호함수] SYMBOL_1ST_IntegerConstant() 를 사용하면 간단하게 처리 할수 있다.
            //}------------------------------------------------------------------------------------------

            //[address]
            //{
                //현재 record 의 {address} 정보를 얻는다.

                if(pDATABASE->REC_Field_Read2(pEXPrecord->recindex, _F_address, NULL, &rec_address) != true) { return(false); }

            //}

            //[기호만들기]
            //{
                SYMBOL_1ST_IntegerConstant(rec_address, symbol);

            //}

        //}

      }
      else
      {
        //이 경우는 일반적인 경우로 G, L, T(함수반환의경우) 만 허용된다.

        if     ((kind & matchDATAkind_variable) || //[변수]
                (kind & matchDATAkind_constant))   //[반환유형이 변수인 함수] 의 [반환공간] 을 상징한다.
        {
          //[변수] 또는 [반환값이 변수형인 함수]

          //"(type)V." 까지 만든다.

          //[type]
          //{
              STR_Add(symbol, "(");
              //{
                  //16진수 최소표기를 사용한다.
                  CONV_LongVal_To_Hex2(pEXPrecord->typelistindex, hexstr);
                  STR_Add(symbol, hexstr);

              //}
              STR_Add(symbol, ")");

          //}

          //[구분]
          //{
              STR_Add(symbol, "V.");

          //}

        }
        //[구조체공용체인수]
        else if((kind & matchDATAkind_pointer)       || //[포인터]
                (kind & matchDATAkind_structpointer) || //[구조체포인터]
                (kind & matchDATAkind_unionpointer))    //[공용체포인터]
        {
          //단순히 전부다 [포인터] 가 되므로 [주소변수] 로 본다.

          //[2008.11.05.수][추가!!!]{-----------------------------------------------------------
          //[인수] 에 사용된 [배열이름] 은 일종의 [변수포인터] 로 보게 되므로 [배열이름] 이지만
          //EXPRESSION_MatchDataKind() 함수에서 [포인터] 성분이 추가 되는데 이 함수에서는
          //[포인터] 인 경우에서 먼저 처리 되므로 자동적으로 [변수] V 로 기호 처리 된다.
          //단, 현재와 같이 [포인터] 의 경우를 먼저 검사해서 처리 해야 제대로 적용된다.
          //}-----------------------------------------------------------------------------------

          //"(unsigned long)V." 까지 만든다.

          //[기호]
          //{
              STR_Add(symbol, "(a)V.");

          //}

        }
        else if((kind & matchDATAkind_struct) || //[구조체]
                (kind & matchDATAkind_union))    //[공용체]
        {
          //[!]{---------------------------------------------------------------------------------
          //[구조체/공용체 이름] 은 [상수포인터] 가 된다.
          //[함수반환공간] 의 <temp> 인 경우도 [반환공간] 자체가 [구조체/공용체] 가 되므로 같다.
          //}------------------------------------------------------------------------------------

          //"(unsigned long)C." 까지 만든다.

          //[기호]
          //{
              STR_Add(symbol, "(a)C.");
              
          //}

          //[순수 구조체/공용체 임을 기록]
          //{
              //[2008.10.15.수][추가!!!]
              isStructOrUnion = true;

          //}

        }
        else if((kind & matchDATAkind_arrayname) ||     //[배열이름]
                (kind & matchDATAkind_constantpointer)) //[상수포인터]
        {
          //[배열이름/상수포인터] 는 [상수포인터] 가 된다.
          
          //"(unsigned long)C." 까지 만든다.

          //[기호]
          //{
              STR_Add(symbol, "(a)C.");
          //}

        }

        //[!]-------------------------------
        //[기호나머지완성]
        //"X.recindex" 부분까지 완성해준다.
        //----------------------------------

        //[!]{--------------------------------------------------------------------------
        //여기서는 [(식)의 사용함수/전역변수/지역변수] 3 가지를 구분해서 처리해야 한다.
        //일단 [식] 에서 사용된 함수만 이 Data() 에서 처리되므로 여기서 처리되는 함수는
        //무조건 [식] 에서 사용된 사용함수 로 보고처리해야 한다.
        //}-----------------------------------------------------------------------------

        //[kind]
        //{
            //현재 record 의 {kind} 정보를 얻는다.
            if(pDATABASE->REC_Field_Read2(pEXPrecord->recindex, _F_kind, NULL, &rec_kind) != true) { return(false); }

        //}

        if((rec_kind == _recKIND_func_def) || //선언함수.
           (rec_kind == _recKIND_func_body))  //본체가 있는 함수.
        {
          //[함수] 인경우.

          //[임시변수] 로 처리되어야 한다.

          //"T.tempindex" 를 붙여준다.

          //[!]{-----------------------------------------------------------------
          //이 경우는 전부 [식] 에서 사용된 return 값을 사용하는 [함수] 가 된다.
          //자동적으로 [임시변수] 로 등록된다.
          //}--------------------------------------------------------------------

          //[segment]
          //{
              STR_Add(symbol, "T.");
          //}

          //[tempindex]
          //{
              //16진수 최소표기를 사용한다.
              CONV_LongVal_To_Hex2(_tempdatabase.recordcount, hexstr);
              STR_Add(symbol, hexstr);

          //}

         //[temprecord]
          //{
              //[!]--------------------------------------------------------------------
              //여기서 직접 생성된 [임시변수] 를 {tempdatabase} 에 추가해 주어야 한다.
              //}----------------------------------------------------------------------

              //symbol 을 저장한다.
              STR_Assign(temprecord.word, symbol);

              //[원래 typelistindex 값 얻기]
              //{
                  //[2008.10.14.화][추가!!!]{-------------------------------------------------------------------------
                  //저장 기호의 정확한 크기를 알기 위하여 원래 typelistindex 값을 저장한다.
                  //이는 함수반환값이 구조체/공용체 자체인 경우 해당 [추가주소] 를 계산할때 필요하다.
                  //기호의 type 정보는 단지 [상수포인터] 로 기록 되므로 실제 구조체/공용체 크기를 알수 없기 때문이다.
                  //}-------------------------------------------------------------------------------------------------

                  //[순수 구조체/공용체 인 경우만 처리]
                  //{
                      //[2008.10.15.수][추가!!!]{---------------------------------------------------------------------
                      //함수 [반환 type] 이 [구조체/공용체 포인터] 등이 아닌 순수 [구조체/공용체] 인 경우만 처리한다.
                      //}---------------------------------------------------------------------------------------------

                      if(isStructOrUnion == true)
                      {
                        temprecord.org_typelistindex = pEXPrecord->typelistindex;

                      }

                  //}

              //}

              //{tempdatabase} 에 저장한다.
              _tempdatabase.Add(&temprecord);

          //}

        }
        else
        {
          //영역을 구분하여 G, L 둘중 어떤것인지 구분한다.

          //[area]
          //{
              //{area} 정보를 얻는다.
              if(pDATABASE->REC_Field_Read2(pEXPrecord->recindex, _F_area, NULL, &rec_area) != true) { return(false); }
          //}

          if     (rec_area == -1)
          {
            //[전역] 인 경우.
            STR_Add(symbol, "G.");

          }
          else if(rec_area > 0)
          {
            //[지역] 인 경우.
            STR_Add(symbol, "L.");

          }
          else
          {
            //해당하지 않는 경우는 에러!!!
            return(false);

          }

          //[recordindex]
          //{
              //--------------------------------------------------
              //16진수 최소표기를 사용한다.
              CONV_LongVal_To_Hex2(pEXPrecord->recindex, hexstr);
              STR_Add(symbol, hexstr);
              //--------------------------------------------------
          //}
          
        }

      }

  //}

  //[기호반환]
  //{
      //완성된 [1차번역기호] 를 반환한다.
      STR_Assign(rSYMBOL, symbol);
  //}

  //이함수는 이상없이 처리되었다.
  return(true);

}

bool __fastcall EXPDATABASE::Data(class  DATABASE  *pDATABASE,
                                  int               pRECindex,
                                  //[2008.10.13.월][추가!!!]
                                  //만들어진 최종 기호를 반환한다.
                                  char              r1stSymbol[],
                                  //[2008.12.14.일][추가!!!]
                                  //{expdatabase} 에는 추가하지 않고 [1차번역기호] 만 얻을지 결정.
                                  //true : [1차번역기호] 만 얻는다.
                                  bool              pTOnlySymbol)
{
  //[2006.03.22.수][생성!!!]{---------------------------------------------------------
  //[식] 의 [DATA] 의 {DATABASE} 의 record-index 를 전달받아서 해당 정보를
  //추출하여 record[] 에 저장할 정보를 만든다음 정보를 저장하는 것 까지 수행한다.
  //
  //[2009.03.22.일][중요수정있음!!!]--------------------------------------------------
  //[구조체/공용체] 의 [포인터] 는 기본적으로 [변수] 이므로 L-Value 로 강제 설정한다.
  //}---------------------------------------------------------------------------------

  //[설명]
  //{
      //이 함수는 TREE_Expression_1_Level() 안에서 [DATA] 정보를 수집하는데 사용한다.
      //pEXP1operator == NULL 이라면 제공되는 정보가 없으므로 모두 내부적으로 추출하여
      //처리해 주어야 한다.
  //}

  //[주의!!!]
  //{
      //data 에는 [상수], [문자열] 도 있을수 있다.
      //이 경우는 아예 해당 tree 에서 완전히 정보 구조체를 정리하여 넘겨 주므로
      //이를 그냥 저장해 주면 된다. 이는 이 함수가 아닌 다른 전담 함수가 존재한다.
  //}

  //[2006.07.15.토][수정!!!]
  //{
      //---------------------------------------------------------------------------------
      //word[] 항목에 symbol 을 저장해 주어야 한다. 이 symbol 을 만든 다음에
      //최종적으로 {EXPDATABASE} 에 record 를 저장해 주어야 한다.
      //
      //FR.kind.type.pointer.array.recindex : [식] 에 사용된 return 값을 사용하는 함수.
      //G.kind.type.pointer.array.recindex  : 전역변수.
      //L.kind.type.pointer.array.recindex  : 지역변수.
      //위의 3 가지만 여기서 처리하면 된다.
      //---------------------------------------------------------------------------------
      //아래는 해당 처리를 위한 함수들이 있으므로 그곳에서 처리하면된다.
      //T.kind.type.pointer.array.recindex   : 임시변수.
      //[문자열/정수상수/실수상수] symbol 의 경우는 별도 처리 부분에서 처리한다.
      //---------------------------------------------------------------------------------
  //}

  //[2006.08.15.화][중요수정!!!]
  //{
      //-------------------------------------------------------------------------------
      //이전과 달리 [배열] 의 경우는 해당 차원을 그대로 array 에 기록한다.
      //array_size[] 정보도 같이 처리해 주어야 한다.
      //이 경우 recindex 정보를 사용하여 [선언정보] 를 참고하여 그대로 copy 하면 된다.
      //[선언정보] 에 array_size 의 정보는 int[] 로 정리되 있다.
      //-------------------------------------------------------------------------------
  //}

  //[2008.12.14.일][수정!!!]
  //{
      //[1차번역문서] => [ASM 문서] 로 번역하는 과정에서 [함수본체시작] 부분의 번역시 [인수] 를
      //pop 으로 읽어 들이는 부분의 번역시 쉽게 처리 할수 있도록 아예 [1차번역] 시에 [함수본체시작]
      //부분의 번역시 [인수] 를 [1차번역기호] 로 만들어 목록을 붙여 준다.
      //이때 [인수] 의 {database} 상의 정보를 가지고 간단하게 [1차번역기호] 를 만들때 이 함수를
      //사용하기 위하여 수정한다.
      //
      // FD.x.{: <LocalTotal> { param-list }
      //
      // 에서 "{ param-list }" 부분을 만들때 이 함수를 사용하여 기호를 만들게 된다.
      //
      //pTOnlySymbol:triue 인 경우는 {expdatabase} 에 구한 exprecord 를 추가하지 않고 단지
      //위의 목적을 위한 [기호] 만 반환하는 것으로 이 함수를 수정한다.

  //}  

  //[VAR]
  //{
      struct  EXPRECORD rec_data;

      int     rec_kind  = 0,
              rec_array = 0;

      //[2006.07.15.토][추가!!!]
      //{
          char symbol[OPT_1st_symbol_length] = {""};

      //}

      //[2006.08.15.화][추가!!!]
      //{
          int  i = 0;

      //}

  //}

  //[처리 가능한가?]
  //{
      if(!(pRECindex >= 0))
      {
        //record 가 없으므로 정보를 처리할수 없다.
        return(false);

      }

  //}

  //[기본처리!!!]
  //{
      //record foramt.
      Format(&rec_data);

      //data record 라는 것을 알린다.
      rec_data.Tdata_Fop = true;

      //data 의 경우는 NULL 로.
      rec_data.word[0] = '\0';

      //[2006.06.27.화][추가!!!]
      //{
          //-------------------------------
          //상수의 경우는 사용하지 않는다.
          rec_data.recindex = -1;

          rec_data._64bit_  = 0;
          //-------------------------------

      //}

  //}

  //[해당 정보 수집!!!]
  //{
      //[kind]
      //{
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_kind, NULL, &rec_kind) != true) { return(false); }

          switch(rec_kind)
          {
            case _recKIND_data       : //일반 data.
            case _recKIND_func_param : //함수 인수.
            {
              //[임시설정!!!]{----------------------------------------------------
              //위의 모든 경우는 일단 전부 L-value 로 설정해 놓는다.
              //다른 정보 없이 여기서 바로 kind 를 결정할수 있다.
              //그러나, [구조체]/공용체] 는 no L-value 가 되므로 이는 다음 부분의
              //typelistindex 추출 부분에서 추가로 type 을 검사하여 수정해 준다.
              rec_data.kind = exprecKIND_lv;
              //}-----------------------------------------------------------------

            } break;

            case _recKIND_func_def   : //선언함수.
            case _recKIND_func_body  : //본체가 있는 함수.
            {
              //[주의!!!][2007.07.14.토][추가!!!]{------------------------------------------------------
              //[사용함수] 는 [반환공간] 이 DATA 가 되는데 반드시 no-lvalue 가 된다.
              //즉, 변수로 보지만 읽을수만 있는 경우이다.
              //이는 안의 값만을 사용하기 때문이다.
              //이 내용은 SYMBOL_1ST_Data() 함수 안에서 [함수] 의 기호처리를 위하여 중요한 의미가 있다.
              //}---------------------------------------------------------------------------------------

              //[사용함수] 의 경우는 no L-value 가 된다(일종의 [값] 이 된다).
              rec_data.kind = exprecKIND_nlv;

            } break;

          }

      //}

      //[typelistindex]
      //{
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_typelistindex, NULL, &rec_data.typelistindex) != true) { return(false); }

          //[2006.05.03.수][추가!!!]
          //{
              //[!]{--------------------------------------------------------
              //구조체, 공용체의 경우는 no L-value 가 되므로 별도 처리한다.
              //이는 [구조체/공용체 이름] 은 [상수포인터] 로 보기 때문이다.
              //}-----------------------------------------------------------

              if     (pDATABASE->TYPELIST_IS_StructType(rec_data.typelistindex) == true)
              {
                //[구조체공용체인수]
                //[인수 구분 처리]
                //{
                    //[2008.11.05.수][수정!!!]{------------------------------------------
                    //[인수] 에 사용된 경우는 할당을 받을수 있는 L-Value 로 보아야 한다.
                    //따라서, 이를 나누어서 처리해 주어야 한다.
                    //}------------------------------------------------------------------

                    if(rec_kind == _recKIND_func_param)
                    {
                      //[인수] 에 사용된 [구조체] 에 해당한다. L-value 가 된다.

                      rec_data.kind = exprecKIND_lv;

                    }
                    else
                    {
                      //[구조체] 에 해당한다. no L-value 가 된다.

                      rec_data.kind = exprecKIND_nlv;

                    }

                //}

              }
              else if(pDATABASE->TYPELIST_IS_UnionType(rec_data.typelistindex) == true)
              {
                //[구조체공용체인수]
                //[인수 구분 처리]
                //{
                    //[2008.11.05.수][수정!!!]{------------------------------------------
                    //[인수] 에 사용된 경우는 할당을 받을수 있는 L-Value 로 보아야 한다.
                    //따라서, 이를 나누어서 처리해 주어야 한다.
                    //}------------------------------------------------------------------

                    if(rec_kind == _recKIND_func_param)
                    {
                      //[인수] 에 사용된 [공용체] 에 해당한다. L-value 가 된다.

                      rec_data.kind = exprecKIND_lv;

                    }
                    else
                    {
                      //[공용체] 에 해당한다. no L-value 가 된다.

                      rec_data.kind = exprecKIND_nlv;

                    }

                //}

              }

          //}

      //}

      //[pointer]
      //{
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_pointer, NULL, &rec_data.pointer) != true) { return(false); }

          //[포인터 는 L-Value 가 된다]
          //{
              //[2009.03.22.일][중요수정!!!]{-----------------------------------------
              //[포인터] 는 기본적으로 [변수] 이므로 반드시 L-Value 가 되어야 한다.
              //[구조체/공용체] 의 포인터인 경우는 위에서 [구조체/공용체] 인지만 보고
              //단순하게 [NL-value] 로 갖에 설정해 주었으므로 여기서 다시 복구된다.
              //}---------------------------------------------------------------------

              if(rec_data.pointer > 0) { rec_data.kind = exprecKIND_lv; }

          //}

      //}

      //[array][2006.08.15.화][중요수정!!!]
      //{
          //[배열이름] 인 경우는 [상수포인터] 가 된다.
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_arraydimension, NULL, &rec_array) != true) { return(false); }

          if(rec_array > 0)
          {
            //[배열] 인 경우이다.

            //[array] 차원을 기록.
            rec_data.array = rec_array;

            //[인수 사용 배열 구분 처리]
            //{
                //[2008.11.04.화][수정!!!]{----------------------------------------------------
                //[인수] 에 [배열] 이 사용된 경우는 [배열이름] 은 [변수포인터] 가 되어야 한다.
                //이때는 [포인터] 로 주소를 전달 받는데만 사용되기 땨문이다.
                //따라서, 이를 구분하여 처리한다.
                //}----------------------------------------------------------------------------

                //이미 위에서 구한 kind 정보를 사용한다.
                if(rec_kind == _recKIND_func_param)
                {
                  //[인수] 에 사용된 경우는 [변수포인터] 가 되어 L-Value 가 되어야 한다.

                  rec_data.kind = exprecKIND_lv;

                }
                else
                {
                  //[배열이름] 은 [상수포인터] 이므로 no-L-value 가 된다.

                  rec_data.kind = exprecKIND_nlv;

                }

            //}

            //[배열차원크기 기록]
            //{
                //이미 [선언정보] 에 각각 [차원의 크기] 정보가 정부 정리되 있으므로
                //그래도 copy 하면 된다.
                for(i = 0; i < rec_data.array; i++)
                {
                  pDATABASE->REC_Field_Read2(pRECindex, _F_arraysize, i, &(rec_data.array_size[i]));

                }

            //}

          }

      //}

      //[recindex][2006.06.27.화][추가!!!]
      //{
          //현재 정보의 {DATABASE} 상의 record-index 를 저장한다.
          rec_data.recindex = pRECindex;

      //}

      //[1차번역기호]
      //{
          //[2007.07.15.일][수정!!!]

          //전용함수로 해당 [1차번역기호] 를 만든다.
          if(SYMBOL_1ST_Data(pDATABASE, &rec_data, symbol) != true) { return(false); }

          //[symbol]
          //{
              //word[] 에 symbol 을 저장한다.
              STR_Assign(rec_data.word, symbol);

          //}

      //}

      //[1차번역기호 반환]
      //{
          //[2008.10.13.월][추가!!!]{-----------------------------------------------------
          //처리한 1차 번역 기호를 반환한다.
          //이는 parser.c 안의 EXPRESSION_DataFunction() 함수 안에서 1 차 번역시 반환값이
          //저장되는 임시변수(T.X) 의 기호를 얻기 위함이다.
          //}-----------------------------------------------------------------------------

          STR_Assign(r1stSymbol, symbol);

      //}

  //}

  //[정보 추가!!!]
  //{
      //[2008.12.14.일][수정!!!]{---------------------------------------------------------
      //[1차번역기호] 만 원하는 경우는 {expdatabase} 에 exprecord 를 추가하지 않아야한다.
      //}---------------------------------------------------------------------------------

      if(pTOnlySymbol != true)
      {
        //record[] 에 추가!!!
        if(Add(&rec_data) != true) return(false);

      }

  //}

  //여기까지 온것은 ok!!!
  return(true);

}

bool __fastcall EXPDATABASE::Data2(class  DATABASE  *pDATABASE,
                                   int               pRECindex,
                                   struct EXPRECORD *rEXPrecord)
{
  //[2006.05.06.토][생성!!!]{-----------------------------------------------------------
  //이 함수는 FUNCPARAM_Assign_Match() 함수에서 함수 [인수] 정보를 바탕으로
  //match 검사에 사용할수 있는 exprecord 정보를 추출하는 용도로 사용한다.
  //Data() 함수와는 {EXPDATABASE} 에 저장하지 않고 exprecord 정보를 반환하는
  //것만 다르고 나머지는 같다.
  //Data() 함수를 그대로 사용하고 있으므로 내부 설명은 Data() 함수를 참고한다.
  //
  //[2007.07.17.화][수정있음!!!]--------------------------------------------------------
  //Data() 가 새롭게 만들어졌으므로 이 함수도 전부 다시 만들었다.
  //
  //[2009.03.22.일][중요수정있음!!!]----------------------------------------------------
  //[구조체/공용체] 의 [포인터] 는 기본적으로 [변수] 이므로 <L-Value> 로 강제 설정한다.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      struct  EXPRECORD rec_data;

      int     rec_kind  = 0,
              rec_array = 0;

      //[2006.07.15.토][추가!!!]
      char symbol[OPT_1st_symbol_length] = {""};

      //[2006.08.15.화][추가!!!]
      int  i = 0;

  //}

  //[처리 가능한가?]
  //{
      if(!(pRECindex >= 0))
      {
        //record 가 없으므로 정보를 처리할수 없다.
        return(false);

      }

  //}

  //[기본처리!!!]
  //{
      //record foramt.
      Format(&rec_data);

      //data record 라는 것을 알린다.
      rec_data.Tdata_Fop = true;

      //data 의 경우는 NULL 로.
      rec_data.word[0] = '\0';

      //[2006.06.27.화][추가!!!]
      //{
          //-------------------------------
          //상수의 경우는 사용하지 않는다.
          rec_data.recindex = -1;

          rec_data._64bit_  = 0;
          //-------------------------------

      //}

  //}

  //[해당 정보 수집!!!]
  //{
      //[kind]
      //{
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_kind, NULL, &rec_kind) != true) { return(false); }

          switch(rec_kind)
          {
            case _recKIND_data       : //일반 data.
            case _recKIND_func_param : //함수 인수.
            {
              //[임시설정!!!]{----------------------------------------------------
              //위의 모든 경우는 일단 전부 L-value 로 설정해 놓는다.
              //다른 정보 없이 여기서 바로 kind 를 결정할수 있다.
              //그러나, [구조체]/공용체] 는 no L-value 가 되므로 이는 다음 부분의
              //typelistindex 추출 부분에서 추가로 type 을 검사하여 수정해 준다.
              rec_data.kind = exprecKIND_lv;
              //}-----------------------------------------------------------------

            } break;

            case _recKIND_func_def   : //선언함수.
            case _recKIND_func_body  : //본체가 있는 함수.
            {
              //[주의!!!]
              //{
                  //[2007.07.14.토][추가!!!]
                  //[사용함수] 는 [반환공간] 이 DATA 가 되는데 반드시 no-lvalue 가 된다.
                  //즉, 변수로 보지만 읽을수만 있는 경우이다.
                  //이는 안의 값만을 사용하기 때문이다.
                  //이 내용은 SYMBOL_1ST_Data() 함수 안에서 [함수] 의 기호처리를 위하여 중요한 의미가 있다.
              //}

              //[사용함수] 의 경우는 no L-value 가 된다.
              rec_data.kind = exprecKIND_nlv;

            } break;

          }

      //}

      //[typelistindex]
      //{
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_typelistindex, NULL, &rec_data.typelistindex) != true) { return(false); }

          //[2006.05.03.수][추가!!!]
          //{
              //구조체, 공용체의 경우는 no L-value 가 되므로 별도 처리한다.
              //이는 [구조체/공용체 이름] 은 [상수포인터] 로 보기 때문이다.

              if     (pDATABASE->TYPELIST_IS_StructType(rec_data.typelistindex) == true)
              {
                //[구조체공용체인수]
                //[인수 구분 처리]
                //{
                    //[2008.11.05.수][수정!!!]{------------------------------------------
                    //[인수] 에 사용된 경우는 할당을 받을수 있는 L-Value 로 보아야 한다.
                    //따라서, 이를 나누어서 처리해 주어야 한다.
                    //}------------------------------------------------------------------

                    if(rec_kind == _recKIND_func_param)
                    {
                      //[인수] 에 사용된 [구조체] 에 해당한다. L-value 가 된다.

                      rec_data.kind = exprecKIND_lv;

                    }
                    else
                    {
                      //[구조체] 에 해당한다. no L-value 가 된다.

                      rec_data.kind = exprecKIND_nlv;

                    }

                //}

              }
              else if(pDATABASE->TYPELIST_IS_UnionType(rec_data.typelistindex) == true)
              {
                //[구조체공용체인수]
                //[인수 구분 처리]
                //{
                    //[2008.11.05.수][수정!!!]{------------------------------------------
                    //[인수] 에 사용된 경우는 할당을 받을수 있는 L-Value 로 보아야 한다.
                    //따라서, 이를 나누어서 처리해 주어야 한다.
                    //}------------------------------------------------------------------

                    if(rec_kind == _recKIND_func_param)
                    {
                      //[인수] 에 사용된 [공용체] 에 해당한다. L-value 가 된다.

                      rec_data.kind = exprecKIND_lv;

                    }
                    else
                    {
                      //[공용체] 에 해당한다. no L-value 가 된다.

                      rec_data.kind = exprecKIND_nlv;

                    }

                //}

              }

          //}

      //}

      //[pointer]
      //{
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_pointer, NULL, &rec_data.pointer) != true) { return(false); }

          //[포인터 는 L-Value 가 된다]
          //{
              //[2009.03.22.일][중요수정!!!]{-----------------------------------------
              //[포인터] 는 기본적으로 [변수] 이므로 반드시 L-Value 가 되어야 한다.
              //[구조체/공용체] 의 포인터인 경우는 위에서 [구조체/공용체] 인지만 보고
              //단순하게 [NL-value] 로 갖에 설정해 주었으므로 여기서 다시 복구된다.
              //}---------------------------------------------------------------------

              if(rec_data.pointer > 0) { rec_data.kind = exprecKIND_lv; }

          //}

      //}

      //[array][2006.08.15.화][중요수정!!!]
      //{
          //[배열이름] 인 경우는 [상수포인터] 가 된다.
          if(pDATABASE->REC_Field_Read2(pRECindex, _F_arraydimension, NULL, &rec_array) != true) { return(false); }

          if(rec_array > 0)
          {
            //[배열] 인 경우이다.

            //[array] 차원을 기록.
            rec_data.array = rec_array;


            //[인수 사용 배열 구분 처리]
            //{
                //[2008.11.04.화][수정!!!]{----------------------------------------------------
                //[인수] 에 [배열] 이 사용된 경우는 [배열이름] 은 [변수포인터] 가 되어야 한다.
                //이때는 [포인터] 로 주소를 전달 받는데만 사용되기 땨문이다.
                //따라서, 이를 구분하여 처리한다.
                //}----------------------------------------------------------------------------

                //이미 위에서 구한 kind 정보를 사용한다.
                if(rec_kind == _recKIND_func_param)
                {
                  //[인수] 에 사용된 경우는 [변수포인터] 가 되어 L-Value 가 되어야 한다.

                  rec_data.kind = exprecKIND_lv;

                }
                else
                {
                  //[배열이름] 은 [상수포인터] 이므로 no-L-value 가 된다.

                  rec_data.kind = exprecKIND_nlv;

                }

            //}

            //[배열차원크기 기록]
            //{
                //이미 [선언정보] 에 각각 [차원의 크기] 정보가 정부 정리되 있으므로
                //그래도 copy 하면 된다.
                for(i = 0; i < rec_data.array; i++)
                {
                  pDATABASE->REC_Field_Read2(pRECindex, _F_arraysize, i, &(rec_data.array_size[i]));

                }

            //}

          }

      //}

      //[recindex][2006.06.27.화][추가!!!]
      //{
          //현재 정보의 {DATABASE} 상의 record-index 를 저장한다.
          rec_data.recindex = pRECindex;

      //}

      //[1차번역기호]
      //{
          //[2007.07.18.수][중요수정!!!]
          //{
              //Data2() 함수는 자체 기호를 만드는 것이 중요하므로 [함수] 의 경우는
              //"FR.index" 에 해당하는 자체 기호를 반환해 주어야 한다.
              //그러므로, [함수] 에 해당하는 경우는 별도로 처리한다.
          //}

          if((rec_kind == _recKIND_func_def) || //선언함수.
             (rec_kind == _recKIND_func_body))  //본체가 있는 함수.
          {
            //이 경우는 전부 [식] 에서 사용된 return 값을 사용하는 [함수] 가 된다.
            SYMBOL_1ST_FunctionData(&rec_data, symbol);

          }
          else
          {
            //전용함수로 해당 [1차번역기호] 를 만든다.
            if(SYMBOL_1ST_Data(pDATABASE, &rec_data, symbol) != true) { return(false); }

          }

          //[symbol]
          //{
              //word[] 에 symbol 을 저장한다.
              STR_Assign(rec_data.word, symbol);

          //}

      //}

  //}


  //[정보 반환!!!][2006.05.06.토][추가!!!]
  //{
      (*rEXPrecord) = rec_data;

  //}


  //여기까지 온것은 ok!!!
  return(true);

}

bool __fastcall EXPDATABASE::Constant(class  DATABASE  *pDATABASE,
                                      bool              pTintFfloat,
                                      //값을 전달 받되 [정수/실수] 를 모두 받아야 하므로 void 형 포인터를 사용한다.
                                      void             *p64bit)
{
  //[2006.03.27.월][작성!!!]{--------------------------------------------------
  //[식1] 에서 [상수] operand 의 exprecord 정보를 생성하고 추가한다.
  //[상수] 에는 [정수/실수] 2 종류가 있는데 [정수] 인 경우는 무조건 long  으로
  //[실수] 인 경우는 무조건 double 로 type 을 만들어야 한다.
  //[정수] : {constant, long, -, noLvalue}
  //[실수] : {constant, double, -, noLvalue}
  //}--------------------------------------------------------------------------

  //[2006.06.27.화][수정!!!]
  //{
      //{expdatabase} 에 추가하는 정보가 증가 했으므로 이를 적용한다.
      //word     : symbol 을 저장. (전용 처리 함수를 사용한다.)
      //recindex : -1 (사용하지 않는다.)
      //_64bit_  : 순수 값을 저장.
      //           실수/정수 를 같이 저장하므로 memory format 으로 저장한다.
  //}


  //[VAR]
  //{
      struct EXPRECORD rec_data;

      //[2006.06.27.화][추가!!!]
      char symbol[OPT_1st_symbol_length] = {""};

      //[2009.01.03.토][추가!!!]
      //{
          int byteX;

      //}

  //}


  //[기본처리!!!]
  //{
      //record foramt.
      Format(&rec_data);

      //data record 라는 것을 알린다.
      rec_data.Tdata_Fop = true;

      //data 의 경우는 NULL 로.
      rec_data.word[0] = '\0';

      //[공통되는 정보 처리]{------------
      rec_data.kind    = exprecKIND_nlv;
      rec_data.pointer = 0;
      //}--------------------------------

      //[2006.06.27.화][추가!!!]
      //{
          //상수의 경우는 사용하지 않는다.
          rec_data.recindex = -1;

          rec_data._64bit_  = 0;
      //}
  //}

  //[type]
  //{
      //정수와 실수에 따라서 정보의 type 이 달라진다.
      if(pTintFfloat == true)
      {
        //[상수 크기 구분 처리]
        //{
            //[2009.01.03.토][수정!!!]{---------------------------------------------------
            //현시점에 모든 상수는 1,2,4,8 의 c-type 크기로 구분처리 하므로,
            //상수 각각의 크기에 맞는 정확한 크기의 c-type 으로 만들어 주어야 한다.
            //[상수] 는 기본적으로 전부 signed 로 보게 되므로 아래의 4개 종류만 가능하다.
            // char, short, int, long
            //}---------------------------------------------------------------------------

            //[크기 얻기]
            //{
                //[2009.03.22.일][중요수정!!!]{--------------------------------------------
                //상수는 그냥 8 byte 로 본다.
                //이는 [식] 에서 계산중 [임시변수] 생성을 위한 것으로 -3 을 하는 경우
                //(-) 연산자에서 결과가 1 byte 크기 [임시변수] 로 생성되어 정확한 결과값을
                //얻을수 없다. 따라서, [상수] 와 연산하는 경우는 무조건 결과를 8 byte 에
                //저장할수 있도록 수정한다.
                //}------------------------------------------------------------------------

                byteX = 8;//Check_C_Type_ByteX(*((__int64 *)p64bit));

            //}

            switch(byteX)
            {
              case 1 : //char.
              {
                pDATABASE->TYPELIST_GetTypeIndex_withNAME("char", &(rec_data.typelistindex));

              } break;

              case 2 : //short.
              {
                pDATABASE->TYPELIST_GetTypeIndex_withNAME("short", &(rec_data.typelistindex));

              } break;

              case 4 : //int.
              {
                pDATABASE->TYPELIST_GetTypeIndex_withNAME("int", &(rec_data.typelistindex));

              } break;

              case 8 : //long.
              {
                pDATABASE->TYPELIST_GetTypeIndex_withNAME("long", &(rec_data.typelistindex));

              } break;

              default :
              {
                //이 경우는 있을수 없는 경우이지만 만일 해당한다면 오류다.
                return(false);

              }

            }

        //}

      }
      else
      {
        pDATABASE->TYPELIST_GetTypeIndex_withNAME("double", &(rec_data.typelistindex));

      }

  //}

  //[symbol 만들기][2006.06.27.화][추가!!!]
  //{
      //[정수/실수 상수] 에 따라서 다른 함수를 사용하여 처리한다.
      if(pTintFfloat == true)
      {
        //[정수상수] symbol 을 만든다.
        SYMBOL_1ST_IntegerConstant(*((__int64 *)p64bit), symbol);

      }
      else
      {
        //[실수상수] symbol 을 만든다.
        SYMBOL_1ST_FloatConstant(*((double *)p64bit), symbol);

      }
  //}

  //[word][2006.06.27.화][추가!!!]
  //{
      //상수인 경우는 symbol 을 집어 넣어 준다.
      STR_Assign(rec_data.word, symbol);
  //}

  //[_64bit_][2006.06.27.화][추가!!!]
  //{
      //64bit 로 저장하므로 [정수/실수 상수] 구분하지 않고 바로 저장한다.
      //[실수] 의 경우는 memory 의 format 그대로 저장되게 된다.
      rec_data._64bit_ = (*((__int64 *)p64bit));
  //}

  //[정보 추가!!!]
  //{
      //record[] 에 추가!!!
      if(Add(&rec_data) != true) return(false);
  //}

  //여기까지 온것은 ok!!!
  return(true);

}

void __fastcall EXPDATABASE::Exprecord_Constant_Make(class  DATABASE   *pDatabase,
                                                     //<true:정수>, <flase:실수>.
                                                     bool               pTintFfloat,
                                                     //[정수/실수] 를 모두 받아야 하므로 <void> 형 포인터를 사용.
                                                     void              *p64bit,
                                                     //<exprecord:상수> 를 반환.
                                                     struct EXPRECORD  *rExprecord)
{
  //[2012.02.22.수][생성!!!]{----------------------------------------------------
  //<EXPDATABASE::Constant()> 를 가지고 만든다.
  //
  //<exprecord:상수> 만 제작하여 반환.
  //
  //이 함수는 <sizeof [식]> 을 처리하기 위하여 필요하고, <sizeof [식]> 의 결과가
  //항상 [최종 자료형의 크기] 로 [상수값] 이 되는데, <sizeof> 는 실제 <code> 로
  //번역되지 않으므로 번역 과정에서 해당 [상수값] 으로 교체해 주기 위한것.
  //
  //<parser.cpp:EXPRESSION_MatchOne()> 에서 실제 [연산자] 처리시 처리 결과를
  //만드는데 사용된ㄷ다.
  //
  //[참고!!!]--------------------------------------------------------------------
  //<맷돌C> 에서는 항상 [정수:(long)], [실수:(double)] 이다.
  //}----------------------------------------------------------------------------

  //[VAR]
  //{ 
      char symbol[OPT_1st_symbol_length] = {""};

  //}


  //[기본처리!!!]
  //{
      //[초기화}{---------
      Format(rExprecord);
      //}-----------------

      //[자료] 임을 표시.
      rExprecord->Tdata_Fop = true;

      //data 의 경우는 NULL 로.
      rExprecord->word[0] = '\0';

      rExprecord->kind    = exprecKIND_nlv;
      rExprecord->pointer = 0;
      rExprecord->array   = 0;

      //상수인 경우는 사용하지 않는다.
      rExprecord->recindex = -1;
      rExprecord->_64bit_  = 0;
      
  //}

  //[<typelistindex> 설정]
  //{
      //[!]{-----------------------------------------------
      //[맷돌C] 는 [정수:(long)], [실수:(double)] 로 고정.
      //}--------------------------------------------------
      
      if(pTintFfloat == true)
      {
        pDatabase->TYPELIST_GetTypeIndex_withNAME("long", &(rExprecord->typelistindex));

      }
      else
      {
        pDatabase->TYPELIST_GetTypeIndex_withNAME("double", &(rExprecord->typelistindex));

      }

  //}

  //[<word> 설정]
  //{
      //[!]{-----------------------------------------
      //[상수] 의 [1차 번역 기호] 를 대신 넣어 준다.
      //}--------------------------------------------

      //[<1차 번역 기호> 만들기]
      //{
          //[!]{---------------------------------------------
          //[정수/실수] 에 따라서 다른 함수를 사용하여 처리.
          //}------------------------------------------------

          if(pTintFfloat == true)
          {
            SYMBOL_1ST_IntegerConstant(*((__int64 *)p64bit), symbol);

          }
          else
          {
            SYMBOL_1ST_FloatConstant(*((double *)p64bit), symbol);

          }

      //}

      //[1차 번역 기호] 로 설정.
      STR_Assign(rExprecord->word, symbol);

  //}

  //[<_64bit_> 설정]
  //{
      //64bit 로 저장하므로 [정수/실수] 를 구분하지 않고 바로 저장.
      //[실수] 의 경우는 [메모리] 내용 그대로 저장된다.
      rExprecord->_64bit_ = (*((__int64 *)p64bit));
      
  //}

}

bool __fastcall EXPDATABASE::String(class  DATABASE     *pDatabase,
                                    int                  pStringlistIndex,
                                    //[2009.01.07.수][수정!!!]
                                    unsigned long long   pStrOfsAdr)
{
  //[2006.03.27.월][작성!!!]{------------------------------------------
  //[식1] 에서 [문자열] operand 의 exprecord 정보를 생성하고 추가한다.
  //문자열은 (char *) type 을 가지는 [배열이름] 으로 간주된다.
  //[문자열] : {variable, char, *, noLvalue}
  //}------------------------------------------------------------------

  //[2006.06.27.화][수정!!!]
  //{
      //--------------------------------------------------------------
      //{expdatabase} 에 추가하는 정보가 증가 했으므로 이를 적용한다.
      //word     : symbol 을 저장. (전용 처리 함수를 사용한다.)
      //recindex : stringlist[] index 를 저장.
      //_64bit_  : 0 (사용하지 않는다.)
      //--------------------------------------------------------------
  //}


  //[VAR]
  //{
      struct EXPRECORD rec_data;

      //[2006.06.27.화][추가!!!]
      char symbol[OPT_1st_symbol_length] = {""};

  //}


  //[기본처리!!!]
  //{
      //record foramt.
      Format(&rec_data);

      //data record 라는 것을 알린다.
      rec_data.Tdata_Fop = true;

      //data 의 경우는 NULL 로.
      rec_data.word[0] = '\0';


      //[공통되는 정보 처리]{------------
      rec_data.kind    = exprecKIND_nlv;
      rec_data.pointer = 1;
      //}--------------------------------

      //[2006.06.27.화][추가!!!]
      //{
          rec_data.recindex = -1;
          rec_data._64bit_  = 0;

      //}

  //}

  //[type]
  //{
      //[문자열] 의 경우는 기본적으로 char 가 된다.
      pDatabase->TYPELIST_GetTypeIndex_withNAME("char", &(rec_data.typelistindex));

  //}

  //[symbol 만들기][2006.06.27.화][추가!!!]
  //{
      //[문자열] symbol 을 만든다.
      SYMBOL_1ST_String(pStrOfsAdr, symbol);

  //}

  //[word][2006.06.27.화][추가!!!]
  //{
      //상수인 경우는 symbol 을 집어 넣어 준다.
      STR_Assign(rec_data.word, symbol);

  //}

  //[recindex][2006.06.27.화][추가!!!]
  //{
      //[문자열] 의 경우는 recindex 값이 stringlist[] 의 index 가 된다.
      rec_data.recindex = pStringlistIndex;

  //}

  //[정보 추가!!!]
  //{
      //record[] 에 추가!!!
      if(Add(&rec_data) != true) return(false);

  //}

  //여기까지 온것은 ok!!!
  return(true);

}

bool __fastcall EXPDATABASE::StringType(struct EXPRECORD  *pExpRecord)
{
  //[2018.07.23.월][작성!!!]{-----------------------------------------------------------
  //전달받은 <pExpRecord> 를 분석해서 [문자열:형] 인지 검사.
  //이 함수는 <DebugViewDisplay_Make_DisplayStr>, <DbgExpTree_Set_Info> 함수에서
  //[검증정보] 가 [문자열] 형태인지 확인하기 위하여 사용.
  //즉, [검증] 시에 [문자열] 내용을 가진 정보이고 출력 대상인지 확인할때 사용된다.
  //금일 [10/16/2/문자열] 로 [문자열] 보기 정보가 추가됐기 때문에 이를 지원하기 위한것.
  //
  //(char *), (char []), (signed char *), (signed char []) 4종류만 해당한다.
  //
  //단, 이런 형을 가졌다고 해서 모두 [문자열] 이라는 것은 아니며(다른 용도일수 있음)
  //[문자열] 을 담는 용도로 사용됐을수 있다는 가능성의 문제.
  //문자열 출력 판단은 [검증:정보] 처리 부에서 담당.
  //
  //[반환값]****************************************************************************
  //
  //1) true  : [문자열] 가능성이 있음.
  //
  //2) false : [문자열] 아님.
  //
  //}-----------------------------------------------------------------------------------

  //DATA.
  if(pExpRecord->Tdata_Fop != true) return(false);

  //(char), (signed char).
  if(!((pExpRecord->typelistindex == 3) || (pExpRecord->typelistindex == 11))) return(false);

  if     (pExpRecord->pointer == 1)
  {
    //[!]{------------------------------------
    //일단 (char *), (signed char *) 인 경우.
    //}---------------------------------------

    //L-Value.
    if(pExpRecord->kind != exprecKIND_lv) return(false);

    //[배열] 이어서는 안된다.
    if(pExpRecord->array > 0) return(false);

  }
  else if(pExpRecord->pointer == 0)
  {
    //[!]{---------------------------------------------
    //이 경우는 (char []), (signed char []) 인지 확인.
    //}------------------------------------------------

    //L-Value.
    if(pExpRecord->kind != exprecKIND_nlv) return(false);

    //반드시 [1차원:배열] 이어야 한다.
    if(pExpRecord->array != 1) return(false);

  }

  //여기까지 온것은 [문자열] 일 가능성이 있는 것으로 본다. 
  return(true);

}

bool __fastcall EXPDATABASE::Operator(struct PARSERINFO *pPARSERinfo,
                                      struct EXPRECORD  *pRECORD,
                                      int                pPRE_BI_POSTkind)
{
  //[2006.03.22.수][수정!!!]{-------------------------------------------------
  //pPARSERinfo 정보를 참고하여 자동으로 record[] 에 연산자 정보를 추가한다.
  //
  //[2012.06.20.수][수정!!!]--------------------------------------------------
  //[연산자] 정보는 <wordIndex> 처리 추가.
  //[실시간 선언 정보판] 의 "->", "." 연산자 [구성원] 처리를 지원하지 위한것.
  //
  //두 [연산자] 외에 다른 [연산자] 는 이 정보를 수집하지 않아도 무방. 
  //}-------------------------------------------------------------------------

  //[정보!!!]{----------------------------------------------------------------------
  //이 함수는 TREE_Expression_1_Level() 안에서 [연산자] 정보를 수집하는데 사용한다.
  //
  //pRECORD == NULL 이라면 제공되는 정보가 없으므로 모두 내부적으로 추출하여
  //처리해 주어야 한다.
  //NULL 이 아닌 경우는 이미 해당 [연산자] 의 모든 정보를 전달 받는 것이므로
  //이 정보 구조체를 그대로 전달해주면 된다.
  //
  //pPRE_BI_POSTkind 로 [접두/접미/이항 연산자] 등을 구분할수 있다.
  //단, (, ) 도 우선순위 판별을 위하여 일단 [연산자] 로 수집은 하는데 이때는
  //xcare 값으로 넘어 오므로 간단하게 판별할수 있다.
  //}-------------------------------------------------------------------------------

  //[VAR]
  //{
      struct EXPRECORD rec_operator;

  //}

  if(pRECORD == NULL)
  {
    //[정보 구조체 format!!!]
    //{
        Format(&rec_operator);
    //}

    //[기본값 정리!!!]
    //{
        //연산자 record 라는 것을 알린다.
        rec_operator.Tdata_Fop = false;

        //나머지는 전부 기본값 그대로 둔다.
    //}

    //[처리용 연산자 저장!!!]
    //{
        //정보에 [연산자] 단어 저장은 추출된 단어를 그대로 저장하는 것이 아니라
        //해당 단어와 대응하는 [처리용 연산자] 를 저장해 주어야 한다.

        Substitution(pPARSERinfo->word, pPRE_BI_POSTkind, rec_operator.word);
    //}

    //[연산자:위치]
    //{
        //[2012.06.20.수][중요추가!!!]{----------------------------------------------------
        //[연산자] 의 [저장소] 상 [위치] 를 기록.
        //[실시간 선언 정보판] 의 "->", "." 연산자의 [구성원] 정보 처리를 지원하기 위한것.
        //}--------------------------------------------------------------------------------

        rec_operator.wordIndex = pPARSERinfo->wordindex;

    //}

    //[정보 추가!!!]
    //{
        //record[] 에 추가!!!
        if(Add(&rec_operator) != true) return(false);
        
    //}

  }
  else
  {
    //
    //NULL 이 아닌 경우는 (typecast) 를 처리하는 경우인데, 여러개의 단어로
    //구성돼 있으므로 해당 처리 tree 함수안에서 완전히 정보를 정리한 것을
    //넘겨 받게 된다.
    //[처리용 연산자] 까지 전부 넘겨 받으므로 구조체 정보를 그대로 추가만 하면 된다.

    //record[] 에 전달받은 정보 구조체 추가!!!
    if(Add(pRECORD) != true) return(false);

  }

  //여기까지 온것은 ok!!!
  return(true);

}

void __fastcall EXPDATABASE::Substitution(char *pWORD,
                                          int   pPRE_BI_POSTkind,
                                          char *pRETURNword)
{
  //[2006.03.22.수][수정!!!]{---------------------------------------------
  //전달받은 소스상의 [연산자] 단어를 [처리용 연산자] 단어로 바꾸어 준다.
  //pPRE_BI_POSTkind 로 [접두/접미/이항 연산자] 들을 서로 가릴수 있으며,
  //( ) 의 경우는 xcare 에 해당하므로 그냥 그대로 저장하면 된다.
  //치환이 불필요한 [연산자] 는 그대로 돌려 주면 된다.
  //처리 시간을 줄이기 위하여 대상이 되는 [접미/접두 연산자] 만 처리한다.
  //
  //[2012.02.22.수][중요추가!!!]------------------------------------------
  //[접두단항 연산자] 로 <sizeof> 연산자 추가.
  //}---------------------------------------------------------------------

  if     (pPRE_BI_POSTkind == defEXPOPERATOR_kind_pre)
  {
    //[접두 연산자] 인 경우.

    if     (STR_Match(pWORD, "+") == true)
    {
      STR_Assign(pRETURNword, "+/");

    }
    else if(STR_Match(pWORD, "-") == true)
    {
      STR_Assign(pRETURNword, "-/");

    }
    else if(STR_Match(pWORD, "++") == true)
    {
      STR_Assign(pRETURNword, "++/");

    }
    else if(STR_Match(pWORD, "--") == true)
    {
      STR_Assign(pRETURNword, "--/");

    }
    else if(STR_Match(pWORD, "*") == true)
    {
      //[포인터] 연산자.
      STR_Assign(pRETURNword, "*/");

    }
    else if(STR_Match(pWORD, "&") == true)
    {
      //[주소] 연산자.
      STR_Assign(pRETURNword, "&/");

    }
    else if(STR_Match(pWORD, "!") == true)
    {
      STR_Assign(pRETURNword, "!/");

    }
    else if(STR_Match(pWORD, "~") == true)
    {
      STR_Assign(pRETURNword, "~/");

    }
    //[2012.02.22.수][추가!!!]{------------------------
    //<sizeof> 연산자 지원으로 <sizeof> 연산자도 추가.
    //이는 형태가 같으므로 같은 [연산자] 를 반환.
    else if(STR_Match(pWORD, "sizeof") == true)
    {
      STR_Assign(pRETURNword, "sizeof");

    }
    //}------------------------------------------------

  }
  else if(pPRE_BI_POSTkind == defEXPOPERATOR_kind_post)
  {
    //[접미 연산자] 인 경우.
    if     (STR_Match(pWORD, "++") == true)
    {
      STR_Assign(pRETURNword, "/++");

    }
    else if(STR_Match(pWORD, "--") == true)
    {
      STR_Assign(pRETURNword, "/--");

    }

  }
  else
  {
    //그 외의 경우는 그대로 전달받은 단어를 다시 반환하면 된다.
    STR_Assign(pRETURNword, pWORD);

  }

  return;

}

bool __fastcall EXPDATABASE::Delete_Bracket(void)
{
  //[2006.04.17.월][생성!!!]{--------------------------------------------------
  //Ranking 정보를 모두 처리한 후에는 우선순위를 모두 판별한 다음이므로 더이상
  //(, ) 는 필요가 없다. 그러므로, 이를 exprecord[] 상에서 완전히 삭제하고,
  //이에 따른 index 위치의 변화가 발생하므로 expoptrrank[] 안의 정보중,
  //exprecordindex 값을 같이 수정해 주어야 한다.
  //}--------------------------------------------------------------------------


  //[VAR]
  //{
      int i = 0;
  //}


  for(i = 0; i < recordcount; )
  {
    //record[i].word 단어가 "(", ")" 인 경우는 해당 record 를 삭제 한다.
    if((STR_Match(record[i].word, "(") == true) || (STR_Match(record[i].word, ")") == true))
    {
      //지정 record 를 삭제 한다.
      if(Delete(i) != true) { return(false); }

      //[참조 정보 수정!!!]
      //{
          //exprecord[] 의 전체 index 가 변동 되었으므로 expoptrrank[] 에서 exprecord-index 를
          //참조 하고 있는 정보를 수정해 주어야 한다.
          //현재 삭제 된 행보다 <= index 값을 전부 -- 해주면 된다.
          //반복 사용 되므로 전용 함수로 처리한다.
          Modify_ExprecordIndex(i);
      //}

      //[!]{-------------------------------------------------------------------
      //현재 i 위치가 삭제 되었으므로 다음 검사는 다시 i 위치 부터 해야 하므로
      //여기서는 i++ 를 하지 않는다.
      //}----------------------------------------------------------------------

    }
    else
    {
      //다음 위치로 수정한다.
      i++;

    }

  }

  //여기까지 온것은 이상 없는 것이다.
  return(true);

}

void __fastcall EXPDATABASE::EXPRECORD_array_size(struct EXPRECORD *pEXPRECORD_D,
                                                  struct EXPRECORD *pEXPRECORD_S,
                                                  bool              pOPERATE)
{
  //[2006.08.16.수][생성!!!]--------------------------
  //exprecord 의 array_size[] 항목의 처리를 전담한다.
  //pOPERATE : true  : "[]" 연산후 처리하는 것이다.
  //           false : 그냥 전체를 copy 해주면 된다.
  //--------------------------------------------------


  //[VAR]
  //{
      int i = 0;

  //}
                                        

  if(pOPERATE == true)
  {
    //[설명]{----------------------------------------------------------------
    //이 경우는 "[]" 연산자 처리후 상태이므로 가장 처음 [크기] 정보를 사용한
    //것으로 보고 처리한다.
    //}----------------------------------------------------------------------

    for(i = 0; i < pEXPRECORD_D->array; i++)
    {
      //[10][20][30][0][0] => [20][30][0][0][0] 이 되어야 한다.
      pEXPRECORD_D->array_size[i] = pEXPRECORD_S->array_size[i + 1];

    }

    //남은 공간 초기화.
    for( ; i < 5; i++)
    {
      //남은 것은 전부 0 으로 채운다.
      pEXPRECORD_D->array_size[i] = 0;

    }

  }
  else
  {
    //[설명]{---------------------------------
    //이 경우는 전체를 그냥 copy 해주면 된다.
    //현재 5 차원 까지만 지원하고  있다.
    //}---------------------------------------

    for(i = 0; i < 5; i++)
    {
      //남은 것은 전부 0 으로 채운다.
      pEXPRECORD_D->array_size[i] = pEXPRECORD_S->array_size[i];

    }

  }

  return;

}

void __fastcall EXPDATABASE::TEST_View(class DATABASE *pDATABASE)
{
  //[2006.03.21.화][생성!!!]{-----------------------------------------------
  //record[] 의 내용을 순서대로 열람할수 있도록 *.txt 파일로 만들어 준다.
  //이 함수는 test 용으로 만든 것이며, 실제 compile 시에 사용되지는 않는다.
  //}-----------------------------------------------------------------------


  //[VAR]
  //{
      //[file-save 를 위한 구조체정보]
      //{
          //중간에 처리되는 모든 문자열을 이곳에 저장한다.
          struct  STRBUF  strbuf;

          AnsiString      filename = "";
      //}

      int             i, j;

      //[2006.06.28.수][추가!!!]
      //{
          //목록의 이름이 "word" 이므로 최소 길이는 4 로 한다.
          int    wordlength_max = 4;
          int    length         = 0;

          char   fieldstr[OPT_str_default_size] = {""};
          char   tempstr[OPT_str_default_size]  = {""};

      //}

      //[2012.04.28.토][추가!!!]
      int  temp = 0;

  //}

  //[초기화]
  //{
      //[2012.04.29.일][추가!!!]{---------------------------------
      //[STRBUF] 는 사용전 반드시 한번만 처음 사용 상태로 만든다.
      //}---------------------------------------------------------

      STRBUF_FirstInit(&strbuf);

  //}

  //[new-buff]
  //{
      //STRBUF.buf[] 를 생성한다.
      //{DATABASE} 용량에 따라 크기를 정해야 하나, 일단 1 Mbyte 정도로 넉넉하게 설정한다.
      STRBUF_New(&strbuf, OPT_databaseviewbuf_size);
  //}


  //[보기 좋게 정리][2006.06.28.수][수정!!!]
  //{
      //2006.08.08.화][추가!!!]
      //{
          //array_recindex 항목을 추가한다.
      //}

      //[설명!!!]{--------------------------------------------------------------------
      //[num]--dt/op--word--kind--type--pointer--array--recindex--_64bit_--array_size
      //5      5      max   4     4     7        5      8         16       40
      //아래의 숫자는 field 를 문자열로 바꾸는 경우의 정해진 길이이다.
      //각각의 field 사이의 공백은 2 개로 한다.
      //}-----------------------------------------------------------------------------

      //[word max 구하기]
      //{
          //word 는 "문자열" 의 길이가 정해져 있지 않으므로 가장 긴 문자열의
          //길이에 맞추기 위하여 가장 긴 길이를 구한다.

          for(i = 0; i < recordcount; i++)
          {
            length = STR_Length(record[i].word);

            //가장 큰 값을 max 값으로 저장한다.
            //같은 경우는 이전 max 값을 그대로 사용한다.
            if(wordlength_max < length)
            {
              //보다 큰 값으로 수정해 준다.
              wordlength_max = length;

            }

          }

          //여기까지 가장 긴 word 길이를 얻었다.

      //}
  //}


  //[record]
  //{
      //[목록추가]
      //{
          STR_SetLength("[num]", 5, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("dt/op", 5, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("word", wordlength_max, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("kind", 4, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("type", 4, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("pointer", 7, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("array", 5, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("recindex", 8, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("_64bit_", 16, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          STR_SetLength("array_size", 40, ' ', fieldstr);
          STRBUF_Add(&strbuf, fieldstr);
          STRBUF_Add(&strbuf, "  ");

          //행을 바꿔준다.
          STRBUF_Add(&strbuf, "\r\n\r\n");
      //}

      //현재 까지 저장된 것 까지만 처리한다.
      for(i=0; i<recordcount; i++)
      {
        //[record-number]
        //{
            STR_Assign(tempstr, "[");
            STR_Add(tempstr, ((AnsiString)IntToStr(i)).c_str());
            STR_Add(tempstr, "]");

            STR_SetLength(tempstr, 5, ' ', fieldstr);

            STRBUF_Add(&strbuf, fieldstr);
            STRBUF_Add(&strbuf, "  ");
        //}

        //[data/operator]
        //{
            if(record[i].Tdata_Fop == true)
            {
              STR_Assign(tempstr, "DATA");

              STR_SetLength(tempstr, 5, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");

            }
            else
            {
              STR_Assign(tempstr, "@");

              STR_SetLength(tempstr, 5, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");

            }
        //}

        //[word]
        //{
            if(record[i].word == NULL)
            {
              STR_Assign(tempstr, "");

              STR_SetLength(tempstr, wordlength_max, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");

            }
            else
            {
              STR_Assign(tempstr, record[i].word);

              STR_SetLength(tempstr, wordlength_max, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");

            }
        //}

        if(record[i].Tdata_Fop == true)
        {
          //[kind]
          //{
              switch(record[i].kind)
              {
                case exprecKIND_lv :
                {
                  STR_Assign(tempstr, "LV");

                  STR_SetLength(tempstr, 4, ' ', fieldstr);

                  STRBUF_Add(&strbuf, fieldstr);
                  STRBUF_Add(&strbuf, "  ");

                } break;

                case exprecKIND_nlv :
                {
                  STR_Assign(tempstr, "NLV");

                  STR_SetLength(tempstr, 4, ' ', fieldstr);

                  STRBUF_Add(&strbuf, fieldstr);
                  STRBUF_Add(&strbuf, "  ");

                } break;

              }
          //}

          //[typelistindex]
          //{
              STR_Assign(tempstr, ((AnsiString)IntToStr(record[i].typelistindex)).c_str());

              STR_SetLength(tempstr, 4, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");
          //}

          //[pointer]
          //{
              STR_Assign(tempstr, ((AnsiString)IntToStr(record[i].pointer)).c_str());

              STR_SetLength(tempstr, 7, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");
          //}

          //[array]
          //{
              STR_Assign(tempstr, ((AnsiString)IntToStr(record[i].array)).c_str());

              STR_SetLength(tempstr, 5, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");
          //}

          //[recindex]
          //{
              STR_Assign(tempstr, ((AnsiString)IntToStr(record[i].recindex)).c_str());

              STR_SetLength(tempstr, 8, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");
          //}

          //[_64bit_]
          //{
              STR_Assign(tempstr, ((AnsiString)(IntToHex(record[i]._64bit_, 16).LowerCase())).c_str());

              STR_SetLength(tempstr, 16, ' ', fieldstr);

              STRBUF_Add(&strbuf, fieldstr);
              STRBUF_Add(&strbuf, "  ");
          //}

          //[array_size]
          //{
              //[2006.08.15.화][대폭수정!!!]
              //정보가 int[] 형태로 되 있으므로 "[10][20]..." 과 같이 선언때와 같은
              //같은 문자열로 만들어 준다.

              for(j = 0; j < record[i].array; j++)
              {
                STR_Assign(tempstr, "[");
                STR_Add(tempstr, ((AnsiString)IntToStr(record[i].array_size[j])).c_str());
                STR_Add(tempstr, "]");
                STRBUF_Add(&strbuf, tempstr);
              }
          //}
        }

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }
  //}

  //다음행으로 넘긴다.
  STRBUF_Add(&strbuf, "\r\n"); //CRLF


  //[expoptrrank]
  //{
      //[목록추가]
      //{
          STRBUF_Add(&strbuf, "[num]\trecindex\t( )\toptr\tleft\r\n\r\n");
      //}

      //현재 까지 저장된 것 까지만 처리한다.
      for(i=0; i<expoptrrankcount; i++)
      {
        //[expoptrrank-number]-----------------------------------------------------------------------------
        STRBUF_Add(&strbuf, "[");
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(i)).c_str());
        STRBUF_Add(&strbuf, "]");
        STRBUF_Add(&strbuf, "\t");

        //[exprecord-index]--------------------------------------------------------------------------------
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(expoptrrank[i].exprecordindex)).c_str()); STRBUF_Add(&strbuf, "\t\t");

        //[bracket]----------------------------------------------------------------------------------------
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(expoptrrank[i].bracket)).c_str());        STRBUF_Add(&strbuf, "\t");

        //[optr]-------------------------------------------------------------------------------------------
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(expoptrrank[i].optr)).c_str());           STRBUF_Add(&strbuf, "\t");

        //[left]-------------------------------------------------------------------------------------------
        STRBUF_Add(&strbuf, ((AnsiString)IntToStr(expoptrrank[i].left)).c_str());           STRBUF_Add(&strbuf, "\t");
        //-------------------------------------------------------------------------------------------------

        //다음행으로 넘긴다.
        STRBUF_Add(&strbuf, "\r\n"); //CRLF

      }
  //}

  //[파일로 저장]
  //{
      //[filename 만들기]
      //{
          //해당 program 실행 경로 안의 "DEBUG" 폴더에 항상 정해진 파일명으로 저장된다.
          filename = (AnsiString)(pDATABASE->programpath) + "DEBUG\\[식1]정보" + IntToStr(temp) + ".txt";

          //파일을 순서대로 구분하기 위한 번호 증가.
          temp++;
          
      //}

      //[저장]
      //{
          //처리된 만큼만 저장하면 되므로 strbuf.count-1 를 filesize 로 사용한다.
          //STRBUF.buf[] 는 문자열을 저장하므로 끝에 '\0' 까지가 count 에 포함되므로,
          //파일로 저장시에는 이 '\0' 은 제외 해 주어야 한다.

          pDATABASE->FILE_Save(filename.c_str(), strbuf.buf, strbuf.count - 1);

      //}

  //}


  //[delete]
  //{
      //생성된 STRBUF.buf[] 를 삭제한다.
      STRBUF_Delete(&strbuf);
      
  //}

  return;

}

void __fastcall EXPDATABASE::OPTRRANK_Format(struct EXPOPTRRANK *pRECORD)
{
  //[2006.03.30.목][생성!!!]{--------------
  //EXPOPTRRANK 정보 구조체를 format 한다.
  //}--------------------------------------

  pRECORD->exprecordindex = -1;
  pRECORD->bracket        = 0;
  pRECORD->optr           = 0;
  pRECORD->left           = 0;

  return;

}

bool __fastcall EXPDATABASE::OPTRRANK_Add(struct EXPOPTRRANK *pRECORD)
{
  //[2006.03.30.목][생성!!!]{---------
  //expoptrrank[] 에 정보를 추가한다.
  //}---------------------------------

  //[저장용량 확인!!!]
  //{
      //더이상 저장할수 없는 경우라면 error 가 된다.
      if(!(expoptrrankcount < OPT_exprecord_size))
      {
        //이 경우는 저장 한도를 넘어선 것이다.
        //아무 처리도 하지 않는다.
        return(false);

      }
  //}

  //[구조체 정보 추가!!!]
  //{
      expoptrrank[expoptrrankcount] = (*pRECORD);
      expoptrrankcount++;
  //}

  //여기까지 온것은 ok!!!
  return(true);

}

void __fastcall EXPDATABASE::OPTRRANK_Move(int pFROMindex,
                                           int pTOindex)
{
  //[2006.03.31.금][생성!!!]{---------------------------
  //from-index 의 record 를 to-index 로 옮긴다.
  //expoptrrank[] 의 정보는 완전히 보존되어야 한다.
  //입력되는 index 값은 모두 범위 내의 값들이어야 한다.
  //}---------------------------------------------------


  //[VAR]
  //{
      //이동할 대상이 되는 from-index 위치의 정보를 저장한다.
      struct EXPOPTRRANK  backup;
      int                 i = 0;
  //}


  //[정보 backup]
  //{
      backup = expoptrrank[pFROMindex];
  //}

  if     (pFROMindex > pTOindex)
  {
    //[from_index - 1] => [to_index] 까지 index 를 -- 하면서 [도미노-copy] 한다.
    for(i = (pFROMindex - 1); i >= pTOindex; i--)
    {
      expoptrrank[i+1]  = expoptrrank[i];

    }

    //to-index 위치에 backup 한 record 를 저장한다.
    expoptrrank[pTOindex] = backup;

  }
  else if(pFROMindex < pTOindex)
  {
    //[from_index + 1] => [to_index] 까지 index 를 ++ 하면서 [도미노-copy] 한다.
    for(i = (pFROMindex + 1); i <= pTOindex; i++)
    {
      expoptrrank[i-1]  = expoptrrank[i];

    }

    //to-index 위치에 backup 한 record 를 저장한다.
    expoptrrank[pTOindex] = backup;

  }
  else
  {
    //(pFROMindex == pTOindex) 인 경우는 아무 의미가 없으므로 처리하지 않는다.

  }

  return;

}

bool __fastcall EXPDATABASE::OperatorRank(char *pOPTRword, int *pOPTRrank)
{
  //[2006.03.30.목][생성!!!]{------------------------
  //[처리용 연산자] 단어를 전달 받아서 이에 해당하는
  //operaotr 의 자체 [우선순위값] 을 반환한다.
  //
  //[2012.02.21.화][추가!!!]-------------------------
  //<sizeof> [연산자[ 추가.
  //}------------------------------------------------

  //[주의!!!]{---------------------------------------------------------------------------------------------
  //[처리용 연산자] 는 일반 연산자와 모양이 약간 다르며, 이는 의미를 확실하게 구분하기 위한 것이다.
  //{10,2} 와 같이 표기된 것은 (typecast) 연산자를 의미한 것으로 첫 문자인 "{" 만 검사하면 바로 알수 있다.
  //연산자 우선순위 값은 클수록 우선 순위가 높다.
  //}------------------------------------------------------------------------------------------------------

  //[rank0]---------------------------------------------------------------------
  if     ((STR_Match(pOPTRword, "[]") == true) ||
          (STR_Match(pOPTRword, "->") == true) ||
          (STR_Match(pOPTRword, ".")  == true))
  {
    (*pOPTRrank) = OPTR_rank_0;

    return(true);

  }
  //[rank1]---------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "!/")  == true) ||
          (STR_Match(pOPTRword, "~/")  == true) ||
          (STR_Match(pOPTRword, "++/") == true) ||
          (STR_Match(pOPTRword, "--/") == true) ||
          (STR_Match(pOPTRword, "+/")  == true) ||
          (STR_Match(pOPTRword, "-/")  == true) ||
          (STR_Match(pOPTRword, "*/")  == true) ||
          (STR_Match(pOPTRword, "&/")  == true) ||
          (STR_Match(pOPTRword, "/++") == true) ||
          (STR_Match(pOPTRword, "/--") == true))
  {
    (*pOPTRrank) = OPTR_rank_1;

    return(true);

  }
  //(typecasr) 의 경우는 symbol 정보가 복잡하므로 별도 처리를 한다.
  else if(pOPTRword[0] == '{')
  {
    (*pOPTRrank) = OPTR_rank_1;

    return(true);

  }
  else if(STR_Match(pOPTRword, "sizeof") == true)
  {
    //[2012.02.21.화][추가!!!]{------------------------------------------
    //<sizeof [식]> 에 사용되는 <sizeof> 는 [접두단항연산자] 로 취급되고
    //<sizeof> 연산자의 [우선순위] 는 (typecast) 와 같다.
    //
    //<sizeof(자료형)> 의 경우는 [함수] 형태의 [피연산자] 로 취급되어
    //결과인 [상수값] 으로 즉시 대체된다.
    //}------------------------------------------------------------------

    (*pOPTRrank) = OPTR_rank_1;

    return(true);

  }
  //[rank2]---------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "*") == true) ||
          (STR_Match(pOPTRword, "/") == true) ||
          (STR_Match(pOPTRword, "%") == true))
  {
    (*pOPTRrank) = OPTR_rank_2;

    return(true);

  }
  //[rank3]---------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "+") == true) ||
          (STR_Match(pOPTRword, "-") == true))
  {
    (*pOPTRrank) = OPTR_rank_3;

    return(true);

  }
  //[rank4]---------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "<<") == true) ||
          (STR_Match(pOPTRword, ">>") == true))
  {
    (*pOPTRrank) = OPTR_rank_4;

    return(true);

  }
  //[rank5]---------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "<")  == true) ||
          (STR_Match(pOPTRword, "<=") == true) ||
          (STR_Match(pOPTRword, ">")  == true) ||
          (STR_Match(pOPTRword, ">=") == true))
  {
    (*pOPTRrank) = OPTR_rank_5;

    return(true);

  }
  //[rank6]---------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "==")  == true) ||
          (STR_Match(pOPTRword, "!=")  == true))
  {
    (*pOPTRrank) = OPTR_rank_6;

    return(true);

  }
  //[rank7]---------------------------------------------------------------------
  else if(STR_Match(pOPTRword, "&")  == true)
  {
    (*pOPTRrank) = OPTR_rank_7;

    return(true);

  }
  //[rank8]---------------------------------------------------------------------
  else if(STR_Match(pOPTRword, "^")  == true)
  {
    (*pOPTRrank) = OPTR_rank_8;

    return(true);

  }
  //[rank9]---------------------------------------------------------------------
  else if(STR_Match(pOPTRword, "|")  == true)
  {
    (*pOPTRrank) = OPTR_rank_9;

    return(true);

  }
  //[rank10]--------------------------------------------------------------------
  else if(STR_Match(pOPTRword, "&&")  == true)
  {
    (*pOPTRrank) = OPTR_rank_10;

    return(true);

  }
  //[rank11]--------------------------------------------------------------------
  else if(STR_Match(pOPTRword, "||")  == true)
  {
    (*pOPTRrank) = OPTR_rank_11;

    return(true);

  }
  //[rank12]--------------------------------------------------------------------
  else if((STR_Match(pOPTRword, "=")   == true) ||
          (STR_Match(pOPTRword, "+=")  == true) ||
          (STR_Match(pOPTRword, "-=")  == true) ||
          (STR_Match(pOPTRword, "*=")  == true) ||
          (STR_Match(pOPTRword, "/=")  == true) ||
          (STR_Match(pOPTRword, "%=")  == true) ||
          (STR_Match(pOPTRword, "&=")  == true) ||
          (STR_Match(pOPTRword, "^=")  == true) ||
          (STR_Match(pOPTRword, "|=")  == true) ||
          (STR_Match(pOPTRword, "<<=") == true) ||
          (STR_Match(pOPTRword, ">>=") == true))
  {
    (*pOPTRrank) = OPTR_rank_12;

    return(true);

  }
  //----------------------------------------------------------------------------

  //여기까지 온것은 해당하지 않는 operator 이므로 error!!!
  return(false);

}

bool __fastcall EXPDATABASE::RankInfo(void)
{
  //[2006.03.30.목][생성!!!]{-----------------------------------------------------------------
  //exprecord[] 에서 [data] 와 () 를 제외한 순수 operator 정보를 expoptrrecord[] 에 수집한다.
  //정보를 수집하면서 ( ) 와 left 우선순위 값은 완전히 처리해 주어야 한다.
  //}-----------------------------------------------------------------------------------------


  //[VAR]
  //{
      //( ) 로 둘러쌓인 겹수를 가지고 있다.
      //( => ++, ) => -- 한다.
      int    bracket_count = 0;

      //작은 값일수록 보다 왼쪽에 위치한 것이다.
      //순수한 연산자를 만날때마다 ++ 시킨다.
      int    left_count = 0;

      int    i = 0;

      //record 정보를 저장할 구조체.
      struct EXPOPTRRANK  expoptrrank;
  //}


  for(i = 0; i < recordcount; i++)
  {
    //[연산자] 의 경우만 처리한다.
    if(record[i].Tdata_Fop == false)
    {
      //연산자의 경우는 ( ) 와 [순수연산자] 의 경우를 따로 처리해야 한다.
      if     (record[i].word[0] == '(')
      {
        bracket_count++;

      }
      else if(record[i].word[0] == ')')
      {
        bracket_count--;

      }
      else
      {
        //이 경우는 [순수연산자] 의 경우이다.

        //[정보추출]
        //{
            //정보 구조체를 포맷한다.
            OPTRRANK_Format(&expoptrrank);

            //record[] 상의 index 를 저장한다.
            expoptrrank.exprecordindex = i;

            //( ) 에 둘러쌓인 겹수를 저장한다.
            expoptrrank.bracket = bracket_count;

            //보다 좌측에 있는 연산자를 우선한다. (값이 작을수록 순위가 높다)
            expoptrrank.left = left_count++;

            //[연산자] 자체 [우선순위 값] 을 추출한다.
            //이 값은 전문 처리 함수를 사용하여 처리한다.
            if(OperatorRank(record[i].word, &(expoptrrank.optr)) != true) { return(false); }
        //}

        //[record 추가]
        //{
            if(OPTRRANK_Add(&expoptrrank) != true) { return(false); }
        //}

      }

    }

  }

  //여기까지 온것은 ok!!!
  return(true);

}

void __fastcall EXPDATABASE::Ranking_Left(void)
{
  //[2006.03.31.금][생성!!!]{------------------
  //left 값을 기준으로 [우선순위] 를 정리한다.
  //left 값은 작을수록 순위가 높다.
  //}------------------------------------------


  //[VAR]
  //{
      int i, j;
  //}


  for(i = 0; i < expoptrrankcount; i++)
  {
    for(j = 0; j < i; j++)
    {
      if(expoptrrank[i].left < expoptrrank[j].left)
      {
        //보다 작은 값이 우선하므로 현재 기준 record 를 j 의 위치로 이동한다.
        OPTRRANK_Move(i, j);

        //원하는 결과를 얻었으므로 현재 기준 record 에 대한 처리는 종료한다.
        break;

      }

    }

  }

  return;

}

void __fastcall EXPDATABASE::Ranking_Optr(void)
{
  //[2006.03.31.금][생성!!!]{------------------------
  //operator 자체의 우선순위 값을 기준으로 정리한다.
  //작은 값일수록 순위가 높다.
  //}------------------------------------------------


  //[VAR]
  //{
      int i, j;
  //}


  for(i = 0; i < expoptrrankcount; i++)
  {
    for(j = 0; j < i; j++)
    {
      if(expoptrrank[i].optr < expoptrrank[j].optr)
      {
        //보다 작은 값이 우선하므로 현재 기준 record 를 j 의 위치로 이동한다.
        OPTRRANK_Move(i, j);

        //원하는 결과를 얻었으므로 현재 기준 record 에 대한 처리는 종료한다.
        break;

      }

    }

  }

  return;

}

void __fastcall EXPDATABASE::Ranking_Bracket(void)
{
  //[2006.03.31.금][생성!!!]{---------------------
  //bracket 값을 기준으로 [우선순위] 를 정리한다.
  //값이 클수록 순위가 높다.
  //}---------------------------------------------


  //[VAR]
  //{
      int i, j;
  //}


  for(i = 0; i < expoptrrankcount; i++)
  {
    for(j = 0; j < i; j++)
    {
      if(expoptrrank[i].bracket > expoptrrank[j].bracket)
      {
        //보다 큰 값이 우선하므로 현재 기준 record 를 j 의 위치로 이동한다.
        OPTRRANK_Move(i, j);

        //원하는 결과를 얻었으므로 현재 기준 record 에 대한 처리는 종료한다.
        break;

      }

    }

  }

  return;

}

void __fastcall EXPDATABASE::Ranking(void)
{
  //[2006.03.31.금][생성!!!]{-------------------------------------------------------
  //expoptrrank[] 에 저장된 정보를 우선순위에 따라서 다시 정렬한다.
  //가장 우선 순위가 높은 것이 index:0 에 위치하도록 한다.
  //[index] 순서대로 처리하면 자동으로 [우선순위] 가 가장 [높은] 것부터 처리되도록.
  //}-------------------------------------------------------------------------------

  //[방법]
  //{
      //-------------------------------------------------------------------------
      //순위 결정도가 낮은 순서대로(left->optr->bracket) 단계별 정리를 수행한다.
      //이렇게 하는 이유는 left 순위가 아무리 높아도 optr 의 최저 순위보다 낮고,
      //역시 optr 의 최고 순위는 bracket 의 최저순위보다 낮기 때문이다.
      //그러므로, 이 수행 결과는 [연산자] [우선순위] 그 자체가 된다.
      //
      //[1단계] : left 값으로 정렬한다.
      //          보다 작은 값이 우선순위가 높다.
      //[2단계] : optr 값으로 정졀한다.
      //          보다 작은 값이 순위가 높다.
      //[3단계] : bracket 값으로 정렬한다.
      //          큰 값일수록 순위가 높다.
      //-------------------------------------------------------------------------
  //}


  //[VAR]
  //{
      int i = 0;
  //}


  //[1단계 : left 로 정렬]
  //{
      Ranking_Left();
  //}

  //[2단계 : optr 로 정렬]
  //{
      Ranking_Optr();
  //}

  //[3단계 : bracket 로 정렬]
  //{
      Ranking_Bracket();
  //}

  //여기까지 왔다면 완전하게 연산자 우선순위대로 모두 정리가 된 것이다.
  return;

}

void __fastcall EXPDATABASE::Modify_ExprecordIndex(int pINDEX)
{
  //[2006.04.17.월][생성!!!]{-----------------------------------------------
  //exprecord[] 상에서 지정된 record 가 삭제 되었으므로 이를 참조 하고 있는
  //expoptrrank[] 상의 정보를 수정해 주어야 한다.
  //지정된 pINDEX 보다 <= index 값을 가진 정보는 index-- 룰 해 주어야 한다.
  //exprecordindex 정보가 해당한다.
  //}-----------------------------------------------------------------------

  //[참고!!!]
  //{
      //-----------------------------------------------------------------------
      //이 함수는 Delete_Bracket() 함수에서 (, ) 의 record 가 삭제되면서
      //index 값의 변화가 발생하므로, 이 index 를 참고 하고 있는 정보의 수정을
      //담당하는 함수로 사용된다.
      //-----------------------------------------------------------------------
  //}


  //[VAR]
  //{
      int  i = 0;
  //}


  for(i = 0; i < expoptrrankcount; i++)
  {
    //수정된 위치 pINDEX 보다 작은 index 의 경우는 위치가 수정되지 않았으므로
    //수정된 위치 pINDEX 보다 크거나 같은 위치의 index 만 index-- 로 수정한다.

    if(expoptrrank[i].exprecordindex >= pINDEX)
    {
      //1 개의 record 가 삭제 되었으므로 -1 만큼 위치를 수정한다.
      expoptrrank[i].exprecordindex--;

    }

  }

  return;

}

void __fastcall EXPDATABASE::Modify_ExprecordIndex2(int pINDEX,
                                                    int pMODIFYcount)
{
  //[2006.04.28.금][생성!!!]{---------------------------------
  //pINDEX       : 수정된 {EXPDATABASE} 의 index 위치.
  //pMODIFYcount : {EXPDATABASE} 에서 delete 된 record 숫자.
  //}---------------------------------------------------------

  //[참고!!!]
  //{
      //---------------------------------------------------------------------
      //이 함수는 {EXPDATABASE} 에서 record 가 삭제되면서 index 값의 변화가
      //발생하므로 이 index 를 참고 하고 있는 정보의 수정을 위하여 사용한다.
      //---------------------------------------------------------------------
  //}


  //[VAR]
  //{
      int  i = 0;
  //}


  for(i = 0; i < expoptrrankcount; i++)
  {
    //수정된 위치 pINDEX 보다 작은 index 의 경우는 위치가 수정되지 않았으므로
    //수정된 위치 pINDEX 보다 크거나 같은 위치의 index 만 수정한다.

    if(expoptrrank[i].exprecordindex >= pINDEX)
    {
      //pMODIFYcount 개의 record 가 삭제 되었으므로 -pMODIFYcount 만큼 위치를 수정한다.
      expoptrrank[i].exprecordindex -= pMODIFYcount;

    }

  }

  return;

}

void __fastcall EXPDATABASE::MATCHINFO_Format(struct MATCHINFO *pMATCHinfo)
{
  //[2006.04.19.수][생성!!!]{--------
  //4개의 exprecord 정보를 포맷한다.
  //}--------------------------------

  Format(&(pMATCHinfo->optr));
  Format(&(pMATCHinfo->left));
  Format(&(pMATCHinfo->right));
  Format(&(pMATCHinfo->result));

  //[2006.04.28.금][추가!!!]
  pMATCHinfo->operator_kind = 0;

  return;

}

void __fastcall EXPDATABASE::Make_FullTypeStr(struct EXPRECORD  *pExpRecord,
                                              char              *rFullTypeStr)
{
  //[2011.06.21.화][생성!!!]{---------------------------------------------------------
  //<exprecord> 를 전달 받아서 [자료형] 을 모두 검토하여 문자열로 만들어 준다.
  //포인터, 배열의 경우는 물론이고 구조체, 공용체인 경우까지 전부 다 반영되어야 한다.
  //이는 [검증보기] 에서 자세한 정보를 보여주기 위한 것이다.
  //
  //예) (unsigned char **)[2][5]
  //    (struct SSS *)[5]
  //}---------------------------------------------------------------------------------

  //[방법!!!]{------------------------------------------------------------
  //<C언어형>       : 이미 {DB:TYPELIST} 에 문자열이 정리돼 있다.
  //<구조체/공용체> : [이름] 만 들어 있어 [구조체/공용체] 인지 알수 없다
  //                  <recindex> 를 참고하여 구분해야 한다.
  //[포인터] 의 경우는 숫자가 있어 쉽게 정리할수 있다.
  //[배열] 의 경우는 [차원] 과 [크기] 정보가 있으므로 쉽게 정리할수 있다.
  //[배열] 의 경우 숫자정보는 [10진수] 를 사용한다.
  //}---------------------------------------------------------------------

  //[VAR]
  //{
      class DATABASE   *database;

      char  decStr[OPT_wordStrSize];

      int   i;


  //}

  //[확인]
  //{
      if(rFullTypeStr == NULL) return;

  //}

  //[초기화]
  //{
      //{DataBase} 주소 얻기.
      DATABASE_GetPtr(&database);

      STR_Assign(rFullTypeStr, "");

  //}

  //[자료형 문자열 얻기]
  //{
      //[!]{------------------------------------------------------------------------------
      //<TYPELIST:rec_index> 가 <-1> 인 경우는 일반 [C 언어 형] 이고 다른 값인 경우는
      //[구조체/공용체] 인 것이므로 이 경우는 {DB} 에서 자세한 정보를 얻어 처리해야 한다.
      //}---------------------------------------------------------------------------------

      STR_Add(rFullTypeStr,"(");

      if(database->typelist[pExpRecord->typelistindex].rec_index < 0)
      {
        //순수한 [C 언어 형] 인 경우다.
        //바로 저장된 문자열을 사용하면 된다.

        STR_Add(rFullTypeStr, database->typelist[pExpRecord->typelistindex].type);

      }
      else
      {
        //[구조체/공용체] 인 경우.
        //이 경우는 {DB}:<record.kind> 로 [구조체] 인지 [공용체] 인지 구분해 주어야 한다.

        switch(database->record[database->typelist[pExpRecord->typelistindex].rec_index].kind)
        {
          case _recKIND_structtype : //구조체 형.
          {
            STR_Add(rFullTypeStr, "struct ");
            STR_Add(rFullTypeStr, database->typelist[pExpRecord->typelistindex].type);

          } break;

          case _recKIND_uniontype : //공용체 형.
          {
            STR_Add(rFullTypeStr, "union ");
            STR_Add(rFullTypeStr, database->typelist[pExpRecord->typelistindex].type);

          } break;

        }

      }

  //}

  //[포인터인가?]
  //{
      //[포인터] 인 경우는 [차원] 만큼 <*> 를 붙여주면 된다.
      if(pExpRecord->pointer > 0)
      {
        //구분을 위한 [공백] 을 하나 붙여준다.
        STR_Add(rFullTypeStr, " ");

        for(i = 0; i < pExpRecord->pointer; i++)
        {
          STR_Add(rFullTypeStr, "*");

        }

      }

      //[포인터] 든 아니든 ")" 로 닫아 주어야 한다.
      STR_Add(rFullTypeStr, ")");

  //}

  //[배열인가?]
  //{
      //[!]{------------------------------------------------------------
      //[배열] 인 경우는 [차원] 에 따라 크기도 같이 정리해 주어야 한다.
      //[크기][크기][...] 형식으로 정리한다.
      //}---------------------------------------------------------------

      if(pExpRecord->array > 0)
      {
        for(i = 0; i < pExpRecord->array; i++)
        {
          STR_Add(rFullTypeStr, "[");

          CONV_LongVal_To_Str(pExpRecord->array_size[i], 0, false, decStr);
          STR_Add(rFullTypeStr, decStr);

          STR_Add(rFullTypeStr, "]");

        }

      }

  //}

  //[!]{-----------------------------
  //여기까지 모든 정보가 정리되었다.
  //}--------------------------------

}

//------------------------------------------------------------------------------
//[TEMPDATABASE]----------------------------------------------------------------
//------------------------------------------------------------------------------

void __fastcall TEMPDATABASE::Init(void)
{
  //[2006.07.22.토][생성!!!]{--------------------
  //{tempdatabase} 의 record 전부를 초기화 한다.
  //
  //[2011.06.10.금][중요수정!!!]
  //}--------------------------------------------

  //[VAR]
  //{
      int  i;

  //}

  //[recordcount]
  //{
      //recordcount 값이 temp [변수] 를 서로 구분하는 번호가
      //되므로 반드시 0 으로 초기화한다.
      recordcount = 0;

  //}

  //[record]
  //{
      for(i = 0; i < OPT_temprecord_size; i++)
      {
        //문자열만 NULL 로 초기화 한다.
        Format(&(record[i]));

      }
  //}

  //[2011.06.10.금][중요추가!!!]{------------------------------------------------------
  //<@TEMP:BASE> 의 [추가주소] 를 [임시변수] 가 추가될때마다 자동으로 계산하기 위한것.
  ofsAdr = 0;
  //}-----------------------------------------------------------------------------------

  return;

}

bool __fastcall TEMPDATABASE::Add(struct TEMPRECORD *pTEMPrecord)
{
  //[2006.07.22.토][생성!!!]{-----------------------------------------------------------
  //전달 받은 record 를 {tempdatabase} 에 추가한다.
  //
  //[2011.06.10.금][중요수정!!!]--------------------------------------------------------
  //[임시변수] 를 생성하여 추가할때 자동으로 [추가주소] 를 계산한다.
  //이는 [검증식] 처리에 [가상 @TEMP 공간] 에 접근하기 위하여 반드시 이 정보가 필요하고
  //[순서대로] 쌓일때 계산하는 것이 가장 간단한 방법이기 때문이다.
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      //[2011.06.10.금][추가!!!]
      //{DATABASE} 의 본체 주소값을 가지는 pointer.
      class   DATABASE  *database;

      long long          size;

  //}

  //[저장용량 확인!!!]
  //{
      //더이상 저장할수 없는 경우라면 error 가 된다.
      if(!(recordcount < OPT_temprecord_size))
      {
        //이 경우는 저장 한도를 넘어선 것이다.
        //아무 처리도 하지 않는다.
        return(false);

      }

  //}


  //[{DataBase} 주소 얻기]{---
  DATABASE_GetPtr(&database);
  //}-------------------------


  //[<추가주소> 설정]
  //{
      //[2011.06.10.금][중요추가!!!]{----------------------------------
      //현재 추가되는 [임시변수] 의 <@TEMP:BASE> [추가주소] 를 구한다.
      //}--------------------------------------------------------------

      pTEMPrecord->ofsAdr = ofsAdr;

  //}

  //[구조체 정보 추가!!!]
  //{
      record[recordcount] = (*pTEMPrecord);
      recordcount++;

  //}

  //[다음 <추가주소> 계산]
  //{
      //[2011.06.10.금][중요추가!!!]{--------------------------------------
      //{ ofsAdr += [현재 추가된 [임시변수] 의 크기] } 로 간단하게 구한다.
      //}------------------------------------------------------------------

      //현재 [임시변수] 크기 얻기.
      database->SIZE_SYMBOL_1ST_Type(pTEMPrecord->word,
                                     pTEMPrecord->org_typelistindex,
                                     &size);

      //다음 [임시변수] [추가주소] 계산.
      ofsAdr += size;

  //}

  //여기까지 온것은 ok!!!
  return(true);

}

void __fastcall TEMPDATABASE::Format(struct TEMPRECORD *pTEMPrecord)
{
  //[2006.07.26.수][생성!!!]{--------
  //전달 받은 record 를 초기화 한다.
  //
  //[2011.06.10.금][중요추가!!!]
  //}--------------------------------

  //[초기화!!!]
  //{
      pTEMPrecord->word[0] = '\0';

      //[2008.10.14.화][추가!!!]
      pTEMPrecord->org_typelistindex = -1;

      //[2011.06.10.금][중요추가!!!]
      pTEMPrecord->ofsAdr = 0;

  //}

  return;

}

void __fastcall TEMPDATABASE::Get_OfsAdrStr_TempTotal(class DATABASE  *pDatabase,
                                                      //문자열을 저장할수 있는 충분한 공간이 있어야 한다.
                                                      char             rOfsAdrStr[],
                                                      //<#TempTotal> 의 1차번역 기호를 반환한다.
                                                      char             rTempTotal[])
{
  //[2007.08.17.금][수정!!!]{-----------------------------------------------------------------------
  //{tempdatabase} 의 temp 변수의 크기를 참고로 각각의 <@TEMP> 를 기준으로 하는
  //offset address 를 순서대로 기록해 준다.
  //단, 크기는 temp record 정보자체의 type 의 크기가 아니라 <1차기호> 안의 type 정보에 맞는
  //실제 크기를 사용해야 한다. 실제 생성된 크기를 참조해야 하므로...
  //구조체/공용체 반환의 경우는 반환 TEMP 자체가 구조체 공용체가 되므로 실제 크기로 처리해야 한다.
  //이는 전용 함수로 쉽게 구할수 있다.

  //아래 형식화 같이 { } 도 포함한 문자열로 기록한다.
  //{ ofsADR0 ofsADR1 ofsADR2 ... }

  //[2008.11.01.토][추가!!!]------------------------------------------------------------------------
  //<#TempTotal> 을 직접 구하여 1차기호로 반환하는 것을 추가한다.
  //이는 어차피 추가주소를 구하려면 각각의 <temp> 크기를 다 알아야 하는데 이 때 이 크기를 다
  //합치면 간단하게 <#TempTotal> 을 구할수 있기 때문이다.

  //[2008.12.10.수][수정!!!]------------------------------------------------------------------------
  //{ ofsADR0:size0 ofsADR1:size1 ofsADR2:size2 ... }
  //로 "ofsADR:size" 의 형식으로 단어를 수정한다.
  //이는 {tempdatasbase} 는 계속 관리 되지 않으므로 정확한 정보를 별도 관리할 필요가 있기 때문이다.
  //<*.gtmp> -> <*.gasm> 변환중 필요성을 발견하고 수정한다.
  //이미 크기 정보로 [추가주소] 문자열을 만듦으로 이왕 구한것 자세하게 정보를 처리하는 것이 좋다.
  //
  //[추가주소] 로도 크기를 추출할수는 있지만 이 경우는 제일 마지막의 [temp] 는 주소만 가지고는
  //[크기]를 알수 없게 된다. 따라서, 위와 같은 방법으로 반드시 처리 되어야 한다.
  //}-----------------------------------------------------------------------------------------------

  //[VAR]
  //{
      int        i;
      long long  size;

      //<@TEMP> 를 기준으로 하는 ofsadr 은 항상 0 부터 시작된다.
      long long  ofsadr = 0;

      //16진수 문자열을 기록한다.
      char       hexstr[OPT_1st_symbol_length] = {""};

      //[2008.11.01.토][추가!!!]
      //{
          //<#TempTotal> 을 가진다.
          long long  tempTotalSize = 0;

      //}

  //}

  //[초기화]
  //{
      STR_Assign(rOfsAdrStr, "{ ");

  //}

  //[주소 문자열 만들기]
  //{
      for(i = 0; i < recordcount; i++)
      {
        //[주소 문자열 합성]
        //{
            //64bit 값을 16진수 최소표기 문자열로 바꾼다.
            CONV_LongVal_To_Hex2(ofsadr, hexstr);

            //[주소] 추가.
            STR_Add(rOfsAdrStr, hexstr);

            //[주소/크기] 구분자를 추가한다.
            STR_Add(rOfsAdrStr, ":");

        //}

        //[다음 주소 계산]
        //{
            //<temp> 의 [1차번역기호] 에서 해당 <temp> 의 크기를 구한다.
            pDatabase->SIZE_SYMBOL_1ST_Type(record[i].word,
                                            record[i].org_typelistindex, //[2008.10.14.화][추가!!!]
                                            &size);

            //[다음 변수 주소] = [지금 주소] + [현재 변수크기] 가 된다.
            ofsadr += size;

        //}

        //[크기 문자열 합성]
        //{
            //[2008.12.10.수][추가!!!]

            //64bit 값을 16진수 최소표기 문자열로 바꾼다.
            CONV_LongVal_To_Hex2(size, hexstr);

            //[크기] 추가.
            STR_Add(rOfsAdrStr, hexstr);
            STR_Add(rOfsAdrStr, " ");

        //}

        //[temptotal 얻기]
        //{
            //[2008.11.01.토][추가!!!]{-------------------------------------------------------
            //각각의 <temp> 크기를 계속 더해주기만 하면 <#TempTotal> 을 간단하게 구할수 있다.
            //}-------------------------------------------------------------------------------

            tempTotalSize += size;

        //}

      }

  //}

  //[후처리]
  //{
      STR_Add(rOfsAdrStr, "} ");

  //}

  //[TempTotal 1st 기호 얻기]
  //{
      //[2008.11.01.토][추가!!!]{-------------------------
      //바로 사용할수 있도록 1차 번역 기호로 반환해 준다.
      //}-------------------------------------------------

      SYMBOL_1ST_IntegerConstant(tempTotalSize, rTempTotal);

  //}

  return;

}

void __fastcall TEMPDATABASE::AsmEncode_Get_OfsAdr(int                  pIndex,
                                                   unsigned long long  *rOfsAdr)
{
  //[2008.12.08.월][생성!!!]{--------------------------------------------------------------
  //asmEncode_OfsAdrList[] 안에 저장되 있는 offset-address 문자열을 바탕으로 지정된 index
  //순번의 [16진수 문자열] 형태의 [주소단어] 를 실제 주소값으로 변환하여 반환한다.
  //이 함수는 *.t -> *.asm 으로 변환시 [1차번역기호] 의 index 부분을 실제 [offset-address]
  //로 변환하여 [ASM 기호] 로 바꾸는데 사용된다.
  //}--------------------------------------------------------------------------------------

  //[VAR]
  //{
      char  ofsAdrWord[OPT_wordStrSize];
      char  hexStr[OPT_wordStrSize];

  //}

  //[지정 단어 추출]
  //{
      //지정 index 순번의 단어를 추출한다.
      STR_Get_LineWord_withSpace(asmEncode_OfsAdrList,
                                 pIndex,
                                 ofsAdrWord);

     //"0x" 를 붙여서 16진수 문자열로 함성한다.
     STR_Assign(hexStr, "0x");
     STR_Add(hexStr, ofsAdrWord);

  //}

  //[값으로 변환]
  //{
      //16진수 문자열을 64bit [주소값] 으로 변환하면서 바로 반환한다.
      CONV_HexStr_To_LongVal(hexStr, (long long *)rOfsAdr);

  //}

  return;

}

void __fastcall TEMPDATABASE::AsmEncode_Get_Size(int         pIndex,
                                                 long long  *rSize)
{
  //[2008.12.10.수][생성!!!]{------------------------------------------------------------
  //asmEncode_SizeList[] 안에 저장되 있는 size 문자열을 바탕으로 지정된 index
  //순번의 [16진수 문자열] 형태의 [크기단어] 를 실제 크기값으로 변환하여 반환한다.
  //이 함수는 *.t -> *.asm 으로 변환시 해당 [temp] 의 [크기] 를 알고자 하는데 사용된다.
  //특히, push, pop 으로 [인수] 등을 처리하는 경우 [크기] 정보가 필요한데 이때 사용된다.
  //
  //push temp <temp>
  //
  //에서 <temp> 가 크기 정보가 되는데 이 정보를 처리할때 이 함수로 구한 크기가 사용된다.
  //}------------------------------------------------------------------------------------

  //[VAR]
  //{
      char  sizeWord[OPT_wordStrSize];
      char  hexStr[OPT_wordStrSize];

  //}

  //[지정 단어 추출]
  //{
      //지정 index 순번의 단어를 추출한다.
      STR_Get_LineWord_withSpace(asmEncode_SizeList,
                                 pIndex,
                                 sizeWord);

     //"0x" 를 붙여서 16진수 문자열로 함성한다.
     STR_Assign(hexStr, "0x");
     STR_Add(hexStr, sizeWord);

  //}

  //[값으로 변환]
  //{
      //16진수 문자열을 64bit [크기값] 으로 변환하면서 바로 반환한다.
      CONV_HexStr_To_LongVal(hexStr, rSize);

  //}

  return;

}





