
//[2009.01.20.화][생성!!!]{-------------------------------------------------
//*.ob1 문서를 번역하여 *.obj 문서를 만들어 준다.
//이 문서는 *.obj 로 만들기 위한 전단계의 모든 [지역라벨] 이 해당 [asm기호]
//로 치환되어 있는 상태로, 그대로 code 로 번역하면 바로 *.obj 가 된다.
//즉, *.obj 를 보다 간단하게 번역하기 위하여 임시로 만드는 문서가 된다.
//}-------------------------------------------------------------------------


#include <vcl.h>
#pragma hdrstop


//[사용 header file]
//{
    #include  "c_define.h"
    #include  "vmos_def.h"

    #include  "ide_library.h"
    #include  "library.h"
    #include  "file.h"
    #include  "database.h"
    #include  "parser.h"
    #include  "asmencoder.h"
    //#include "object1st.h"
    #include  "object.h"

    #include  "ide_msgbox.h"
    #include  "msg_msg.h"

    //[2011.04.29.금][추가!!!]
    #include  "buildStatus.h"

//}

//ide_msgbox_Form->_MsgBox(d_MSGBOX_error, debugStr);

bool __fastcall Object(char  *pTempFileName)
{
  //[2009.01.20.화][생성!!!]{-----------------------------------------------------------
  //<*.ob1> 를 읽어서 <*.obj> 을 만들어 준다.
  //
  //[함수라벨]
  //
  // - [함수라벨] 은 <Link> 시 최종 확정 되므로 그대로 추가한다.
  // - 추가로, [행번호] 의 주소를 확정하기 위하여 [행번호] 저장소에도 같이 추가해 준다.
  //
  //[명령어]
  //
  // - 그대로 Code 로 바꾸어 <*.obj> 에 추가한다.
  //   [명령어] 는 항상 첫번째 단어 위치에만 존재 한다.
  //   현재 [명령어] 는 1 Byte 이므로 <LittleEndian> 처리를 할필요는 없다.
  //
  //[피연산자]
  //
  // - [함수라벨]
  //
  //   -> <Link> 시 _CODE_:BASE 로한 [추가주소] 가 결정 되므로 그대로 추가한다.
  //
  // - [일반 피연산자]
  //
  //   -> [ASM 기호] 를 읽어서 <타입> 과 <값> 으로 분리 하여 각각 Code 화 한뒤
  //      <LittleEndian> 처리를 해서 각각 순서대로 추가한다.
  //      단, 이 것이 한개의 [피연산자] 이므로 추가시 한 덩어리로 추가해야 한다.
  //
  //}-----------------------------------------------------------------------------------

  //[VAR]
  //{
      class  DATABASE  *database;
      int    result = 0;

      //처리에 필요한 정보 구조체는 한개만 생성하면 된다.
      struct OBJECTINFO  objectInfo;

      //부가 정보를 관리한다.
      //수집 라벨 등 수많은 정보를 관리 하므로 용량이 크므로 별도로 관리 되어야 한다.
      struct OBJECTINFOETC  objectInfoEtc;

  //}

  //[DATABASE 위치 얻기]
  //{
      DATABASE_GetPtr(&database);

  //}

  //[*.ob1 문서 열기]
  //{
      //[!]{-----------------------------------------------------------
      //<*.ob1> 문서를 열어준다.
      //{DATABASE} 안의 [문서정보구조체] 에 문서 크기 만큼 생성해준다.
      //}--------------------------------------------------------------

      if(FILE_Open2(pTempFileName,
                    (unsigned char **)(&(database->fileinfo.buf)),
                    &(database->fileinfo.size),
                    &(database->fileinfo.handle)) != true)
      {
        //<*.ob1> 문서열기 오류로 더이상 진행하지 않고 바로 종료한다.
        return(false);

      }

  //}

  //[tempfile][*.obj file buffer 생성]
  //{
      //[tempfile 저장소 생성]
      //{
          //*.obj 문서는 *.ob1 문서의 2 배 정도면 충분하다.
          TEMPFILE_Create(database->fileinfo.size * OPT_ObjFile_SizeFactor);

      //}

      //[<*.obj> 문서 이름 만들기]
      //{
          //<*.obj> 문서 이름을 미리 만들어 놓는다.
          //*.c 파일 이름을 그대로 사용하고 확장자만 바꾼다.
          TEMPFILE_MakeFileName(pTempFileName, "gobj");

      //}

  //}

  //[정보 초기화]
  //{
      //*.ob1 문서가 저장되 있는 위치를 얻는다.
      objectInfo.ob1Buf  = database->fileinfo.buf;

      //*.obj 문서가 저장중인 위치를 얻는다.
      objectInfo.objBuf  = database->tempfile.buf;

      //총 행수를 얻는다.
      objectInfo.lineTotalCount = STR_Get_LineCount(objectInfo.ob1Buf);

      objectInfo.lineStartIndex = 0;

      objectInfo.line           = 0;

      objectInfo.word[0]        = '\0';

      objectInfo.wordStartIndex = 0;

      //[부가정보] 의 위치를 얻는다.
      //용량이 크므로 [주소] 로 관리한다.
      objectInfo.infoEtc        = &objectInfoEtc;

      //[부가 정보 초기화]
      //{


      //}

  //}


  //[가상기계 제작 진행창]
  //{
      //[2011.04.29.금][추가!!!]{--------------------------------------
      //현재 처리중인 [문서정보] 를 [가상기계 제작 진행창] 에 보여주고
      //관련설정을 수행한다.
      //}--------------------------------------------------------------

      //[!]{-------------------------------------------------------------------------
      //문서를 읽어들일때 [행수] 를 얻지 않으므로, 여기서 직접 얻어서 전달해야 한다.
      //단, <STR_Get_LineCount()> 함수는 처리 시간이 많이 걸리는데 주의한다.
      //}----------------------------------------------------------------------------

      buildStatus_Form->_fileLineCount = objectInfo.lineTotalCount;
      buildStatus_Form->_FileInfo(pTempFileName, buildStatus_Form->_fileLineCount);

  //}


  //[Object 처리]
  //{
      //[1단계 처리]
      //{
          OBJECT:

          //[Win7 <응답이 없는 상태> 해결]
          //{
              //[2010.09.26.일][중요추가!!!]{---------------------------------------------------------------
              //WinXP 에서는 아무 문제가 없었는데, Win7 에서는 [무한반복] 이 계속되는 경우
              //일정 시간이 지나면 [응답이 없는 상태] 로 지정되어 [맷돌] 과 통신시에 [시간제한] 에
              //계속 걸리는 문제가 발생하고, [하얗게] 되는 문제가 발생한다.
              //보기에도 좋지 않고, 통신에도 문제가 방생하므로 [무한반복] 부분에 [외부 알림문 확인] 을 넣어
              //이런 형상이 발생하지 않도록 수정한다.
              //이는 [링크] 등 다른 부분도 마찬가지이므로 대규모 [무한반복] 을 처리하는 부분에는 전부
              //이 문장을 넣어 준다.
              //}-------------------------------------------------------------------------------------------

              Application->ProcessMessages();

          //}

          //[가상기계 제작 진행창]
          //{
              //[2011.04.29.금][추가!!!]{--------------------------------------------
              //[중지] 요청이 있는 경우는 더이상 처리하지 않고 종료해야 한다.
              //일단, [오류] 로 처리하고, [오류 문자열] 에 [중지요청] 임을 알려준다.
              //}--------------------------------------------------------------------

              if(buildStatus_Form->Visible == false)
              {
                //[!]{-------------------------------------------------------
                //이 경우는 [즁지] 요청으로 간주하고 여기서 처리를 종료한다.
                //}----------------------------------------------------------

                msg_msg_Form->_PrintAddLine
                (d_msg_msg,
                 "\r\n"
                 "[ 가상기계 제작 취소! ]\r\n"
                 "사용자 요청으로 가상기계 제작이 [취소] 되었습니다.");

                //return(false);
                //[2011.05.02.월][추가!!!]
                //동적 생성된 저장소 삭제를 위하여 종료처리를 위한 곳으로 이동한다.
                goto lbError;

              }

          //}

          //여기서부터 또 하나의 행이 시작되는 것이다.

          //[현재 행에 내용이 있는가?]
          //{
              //현재 행에 처리할 것이 없다면 다음 행으로 넘어가야 한다.
              //[첫번째 단어] 만 추출해 보면 간단하게 알수 있다.
              Object_GetWord(&objectInfo, 0);

              //첫 단어가 아무것도 없는 경우는 이 행에는 처리할게 없는 것이므로 다음 행으로 넘긴다.
              if(STR_Match(objectInfo.word, "") == true) { goto OBJECT_LINE_END; }

          //}

          //[함수라벨]
          //{
              result = Tree_Object_FuncLabel(&objectInfo);

              switch(result)
              {
                case yes   :  goto OBJECT_LINE_END;
                case no    :  break;

              }

          //}

          //[명령행]
          //{
              result = Tree_Object_OpcodeLine(&objectInfo);

              switch(result)
              {
                case yes   :  goto OBJECT_LINE_END;
                case no    :  break;

              }

          //}

          //[문자열 code]
          //{
              result = Tree_Object_StringCode(&objectInfo);

              switch(result)
              {
                case yes   :  goto OBJECT_LINE_END;
                case no    :  break;

              }

          //}

          OBJECT_LINE_END:


          //[가상기계 제작 진행창]
          //{
              //[2011.04.29.금][추가!!!]{-------------------------------------------
              //현재 처리중인 [현재 행] 과 [총 처리 행수] 를 처리한다.
              //여기서 처리하는 이유는 [듬성 듬성] 처리하여 정보는 보여주되
              //처리 시간 증가에 영향을 주지않기 위함이다.
              //
              //이 문서는 전부 1 행 단위로 처리 되므로 [문서량/10] 단위로 처리한다.
              //}-------------------------------------------------------------------

              if((buildStatus_Form->_fileLineCount/10) > 0)
              {
                if(objectInfo.line%(buildStatus_Form->_fileLineCount/10) == 0)
                {
                  //[현재행] 보여주기.
                  buildStatus_Form->_LineNum(objectInfo.line);

                  //[전체 처리 행수] 보여주기.
                  buildStatus_Form->_TotalLineNum();

                }

              }
              else
              {
                //[현재행] 보여주기.
                buildStatus_Form->_LineNum(objectInfo.line);

                //[전체 처리 행수] 보여주기.
                buildStatus_Form->_TotalLineNum();

              }

          //}

          //각각의 [행] 을 처리한 다음에 다음 [행] 을 지정하거나 문서의 끝에 도달한 경우 등의 처리를 수행한다.

          //[문서의 끝인가?]
          //{
              //현재 [행번호 + 2] 이 총 행수와 같다면 모든 행을 다 처리한 것이다.
              //이는 <*.ob1> 문서에 빈행은 없으나 맨 마지막 문서행은 내용이 없는 CRLF 만 있기 때문이다.

              if((objectInfo.line + 2) >= objectInfo.lineTotalCount)
              {
                //모든 행을 다 처리 하였으므로 문서를 저장하는 곳으로 이동한다.
                goto OBJECT_FILE_SAVE;

              }
              else
              {
                //[다음행 지정]
                //{
                    //다음 행의 시작 index 를 구한다.
                    STR_Get_NextLineStartIndex(objectInfo.ob1Buf,
                                               objectInfo.lineStartIndex,
                                               &(objectInfo.lineStartIndex));

                    //행 순번 증가.
                    objectInfo.line++;

                    //[가상기계 제작 진행창]
                    //{
                        //[2011.04.29.금][추가!!!]{----------------------------------------
                        //[가상기계 제작 상태 창] 에 [총 처리 행수] 정보를 표시하기 위하여
                        //이 창에서 관리하는 [총 처리 행수] 환경변수를 수정해 준다.
                        //}----------------------------------------------------------------

                        //행이 증가할때 마다 같이 증가시켜 준다.
                        buildStatus_Form->_totalLineNum++;

                    //}

                //}

                //다시 다음 행을 처리한다.
                goto OBJECT;

              }

          //}

      //}

  //}


  OBJECT_FILE_SAVE:

  lbOk:
  //{
      //[tempfile][*.obj file 저장]
      //{
          //[!]{---------------------------------------------------
          //tempfile [저장소] 의 내용을 <*.obj> 문서로 저장한다.
          //저장할 파일의 이름은 이미 사전에 만들어진 상태이다.
          //해당 buffer 의 삭제는 아래 함수에서 자동으로 처리된다.
          //}------------------------------------------------------

          TEMPFILE_Save();

      //}

      //[2012.04.28.토][추가!!!]
      database->FILEINFO_Delete(&(database->fileinfo));

      return(true);

  //}

  lbError:
  //{
      //[2011.05.02.월][추가!!!]{------------------------------------------------------
      //이미 생성된 저장소가 있으므로 반드시 [삭제] 해야 한다.
      //원래는 <TEMPFILE_Save()> 에서 저장시 자동 [삭제] 되지만 중간에 종료하는 경우는
      //이 과정을 거치지 않기 때문에 별도로 [삭제] 해 주어야 한다.
      //}------------------------------------------------------------------------------

      TEMPFILE_Delete();

      //[2012.04.28.토][추가!!!]
      database->FILEINFO_Delete(&(database->fileinfo));

      return(false);

  //}

}

int __fastcall Tree_Object_FuncLabel(struct OBJECTINFO  *prObjectInfo)
{
  //[2009.01.21.수][생성!!!]{----------------------------------
  //[함수라벨] 부분을 처리한다.
  //[함수영역] 의 시작으로 볼수 있으므로 관련 처리도 수행한다.
  //}----------------------------------------------------------

  //[처리내용]
  //{
      // ":함수이름:" 의 [전역라벨] 이라면 <*.obj> 문서에 그대로 추가한다.
      //또한, [행번호] 만 저장하는 <*.$> 에도 그대로 추가해 주어야 한다.

  //}

  //[VAR]
  //{
      struct OBJECTINFO  objectInfo_Backup;

  //}

  //[정보대피]
  //{
      //이 함수에 해당하지 않는 경우를 대비하여 정보를 대피시킨다.
      objectInfo_Backup = (*prObjectInfo);

  //}

  //[첫 단어 추출]
  //{
      //현재 행의 첫 단어를 추출한다.
      Object_GetWord(prObjectInfo, 0);

  //}

  //[함수라벨 인가?]
  //{
      //[함수라벨] 은 유일한 [전역라벨] 로 단어의 시작이 ":" 문자로 시작한다.
      if(prObjectInfo->word[0] != ':')
      {
        //[함수라벨] 이 아니므로 이 함수에 해당하지 않는다.

        //[정보복구]
        //{
            (*prObjectInfo) = objectInfo_Backup;

        //}

        //해당하지 않으므로 여기서 종료한다.
        return(no);

      }

  //}

  //[*.obj 에 추가]
  //{
      TEMPFILE_Add(prObjectInfo->word); TEMPFILE_Add(" \r\n");

  //}

  return(yes);

}

int __fastcall Tree_Object_OpcodeLine(struct OBJECTINFO  *prObjectInfo)
{
  //[2009.01.21.수][생성!!!]{-----------------------------------------------------------
  //[첫 단어] 위치의 [명령어] 를 전부 식별하여 처리한다.
  //
  //1) [첫단어] 가 [명령어] 인지 확인.
  //
  //2) [명령어] 의 해당 code 로 바꾸어 <*.obj> 에 추가
  //   => 현재 [명령어] 는 1 Byte 크기를 가지므로 <LittleEndian> 으로 바꿀 필요는 없다.
  //
  //3) 뒤에 오는 [피연산자] 를 각각의 code 로 바꾼뒤 <*.obj> 에 추가한다(공통처리).
  //   => 전부 1 Byte 이상이므로 반드시 <LittleEndian> 으로 바꾸어 추가 한다.
  //      [피연산자] 는 각각의 [한덩어리] 로 보고 역시 단어 단위로 추가해야 한다.
  //
  //[주의!!!]---------------------------------------------------------------------------
  //16진수 최소 표기가 아니라! 반드시 크기에 맞는 Digit 로 표기해야 한다.
  //이제는 실제 Code 화 되는 것이므로.
  //}-----------------------------------------------------------------------------------

  //[처리내용]
  //{
      //[명령행] 이라면 각각을 전부 Code 로 번역한뒤 <LittleEndian> 으로 변경후 <*.obj> 에 추가한다.
      //실제적으로 Object Code 번역하는 부분이다.

  //}

  //[VAR]
  //{
      struct OBJECTINFO  objectInfo_Backup;

      char   code[OPT_wordStrSize];

      int    i;

  //}

  //[정보대피]
  //{
      //이 함수에 해당하지 않는 경우를 대비하여 정보를 대피시킨다.
      objectInfo_Backup = (*prObjectInfo);

  //}

  //[첫 단어 추출]
  //{
      //현재 행의 첫 단어(명령어 위치)를 추출한다.
      Object_GetWord(prObjectInfo, 0);

  //}

  //[명령어 구분 처리]
  //{
      //[명령어] 는 간단하게

      //연산자 비교.

      if     (STR_Match(prObjectInfo->word, "[]") == true)
      {
        //[OPCODE : 1]
        Object_Opcode(prObjectInfo, 1);

      }
      else if(STR_Match(prObjectInfo->word, "->") == true)
      {
        //[OPCODE : 2]
        Object_Opcode(prObjectInfo, 2);

      }
      else if(STR_Match(prObjectInfo->word, ".") == true)
      {
        //[OPCODE : 3]
        Object_Opcode(prObjectInfo, 3);

      }
      else if(STR_Match(prObjectInfo->word, "!/") == true)
      {
        //[OPCODE : 4]
        Object_Opcode(prObjectInfo, 4);

      }
      else if(STR_Match(prObjectInfo->word, "~/") == true)
      {
        //[OPCODE : 5]
        Object_Opcode(prObjectInfo, 5);

      }
      else if(STR_Match(prObjectInfo->word, "++") == true)
      {
        //[OPCODE : 6]
        Object_Opcode(prObjectInfo, 6);

      }
      else if(STR_Match(prObjectInfo->word, "--") == true)
      {
        //[OPCODE : 7]
        Object_Opcode(prObjectInfo, 7);

      }
      else if(STR_Match(prObjectInfo->word, "-/") == true)
      {
        //[OPCODE : 8]
        Object_Opcode(prObjectInfo, 8);

      }
      else if(STR_Match(prObjectInfo->word, "*/") == true)
      {
        //[OPCODE : 9]
        Object_Opcode(prObjectInfo, 9);

      }
      else if(STR_Match(prObjectInfo->word, "&/") == true)
      {
        //[OPCODE : 10]
        Object_Opcode(prObjectInfo, 10);

      }
      else if(STR_Match(prObjectInfo->word, "*") == true)
      {
        //[OPCODE : 11]
        Object_Opcode(prObjectInfo, 11);

      }
      else if(STR_Match(prObjectInfo->word, "/") == true)
      {
        //[OPCODE : 12]
        Object_Opcode(prObjectInfo, 12);

      }
      else if(STR_Match(prObjectInfo->word, "%") == true)
      {
        //[OPCODE : 13]
        Object_Opcode(prObjectInfo, 13);

      }
      else if(STR_Match(prObjectInfo->word, "+") == true)
      {
        //[OPCODE : 14]
        Object_Opcode(prObjectInfo, 14);

      }
      else if(STR_Match(prObjectInfo->word, "+*") == true)
      {
        //[OPCODE : 15]
        Object_Opcode(prObjectInfo, 15);

      }
      else if(STR_Match(prObjectInfo->word, "-") == true)
      {
        //[OPCODE : 16]
        Object_Opcode(prObjectInfo, 16);

      }
      else if(STR_Match(prObjectInfo->word, "-*") == true)
      {
        //[OPCODE : 17]
        Object_Opcode(prObjectInfo, 17);

      }
      else if(STR_Match(prObjectInfo->word, "<<") == true)
      {
        //[OPCODE : 18]
        Object_Opcode(prObjectInfo, 18);

      }
      else if(STR_Match(prObjectInfo->word, ">>") == true)
      {
        //[OPCODE : 19]
        Object_Opcode(prObjectInfo, 19);

      }
      else if(STR_Match(prObjectInfo->word, "<") == true)
      {
        //[OPCODE : 20]
        Object_Opcode(prObjectInfo, 20);

      }
      else if(STR_Match(prObjectInfo->word, "<=") == true)
      {
        //[OPCODE : 21]
        Object_Opcode(prObjectInfo, 21);

      }
      else if(STR_Match(prObjectInfo->word, ">") == true)
      {
        //[OPCODE : 22]
        Object_Opcode(prObjectInfo, 22);

      }
      else if(STR_Match(prObjectInfo->word, ">=") == true)
      {
        //[OPCODE : 23]
        Object_Opcode(prObjectInfo, 23);

      }
      else if(STR_Match(prObjectInfo->word, "==") == true)
      {
        //[OPCODE : 24]
        Object_Opcode(prObjectInfo, 24);

      }
      else if(STR_Match(prObjectInfo->word, "!=") == true)
      {
        //[OPCODE : 25]
        Object_Opcode(prObjectInfo, 25);

      }
      else if(STR_Match(prObjectInfo->word, "&") == true)
      {
        //[OPCODE : 26]
        Object_Opcode(prObjectInfo, 26);

      }
      else if(STR_Match(prObjectInfo->word, "^") == true)
      {
        //[OPCODE : 27]
        Object_Opcode(prObjectInfo, 27);

      }
      else if(STR_Match(prObjectInfo->word, "|") == true)
      {
        //[OPCODE : 28]
        Object_Opcode(prObjectInfo, 28);

      }
      else if(STR_Match(prObjectInfo->word, "&&") == true)
      {
        //[OPCODE : 29]
        Object_Opcode(prObjectInfo, 29);

      }
      else if(STR_Match(prObjectInfo->word, "||") == true)
      {
        //[OPCODE : 30]
        Object_Opcode(prObjectInfo, 30);

      }
      else if(STR_Match(prObjectInfo->word, "=") == true)
      {
        //[OPCODE : 31]
        Object_Opcode(prObjectInfo, 31);

      }
      else if(STR_Match(prObjectInfo->word, "+=") == true)
      {
        //[OPCODE : 32]
        Object_Opcode(prObjectInfo, 32);

      }
      else if(STR_Match(prObjectInfo->word, "+=*") == true)
      {
        //[OPCODE : 33]
        Object_Opcode(prObjectInfo, 33);

      }
      else if(STR_Match(prObjectInfo->word, "-=") == true)
      {
        //[OPCODE : 34]
        Object_Opcode(prObjectInfo, 34);

      }
      else if(STR_Match(prObjectInfo->word, "-=*") == true)
      {
        //[OPCODE : 35]
        Object_Opcode(prObjectInfo, 35);

      }
      else if(STR_Match(prObjectInfo->word, "*=") == true)
      {
        //[OPCODE : 36]
        Object_Opcode(prObjectInfo, 36);

      }
      else if(STR_Match(prObjectInfo->word, "/=") == true)
      {
        //[OPCODE : 37]
        Object_Opcode(prObjectInfo, 37);

      }
      else if(STR_Match(prObjectInfo->word, "%=") == true)
      {
        //[OPCODE : 38]
        Object_Opcode(prObjectInfo, 38);

      }
      else if(STR_Match(prObjectInfo->word, "&=") == true)
      {
        //[OPCODE : 39]
        Object_Opcode(prObjectInfo, 39);

      }
      else if(STR_Match(prObjectInfo->word, "^=") == true)
      {
        //[OPCODE : 40]
        Object_Opcode(prObjectInfo, 40);

      }
      else if(STR_Match(prObjectInfo->word, "|=") == true)
      {
        //[OPCODE : 41]
        Object_Opcode(prObjectInfo, 41);

      }
      else if(STR_Match(prObjectInfo->word, "<<=") == true)
      {
        //[OPCODE : 42]
        Object_Opcode(prObjectInfo, 42);

      }
      else if(STR_Match(prObjectInfo->word, ">>=") == true)
      {
        //[OPCODE : 43]
        Object_Opcode(prObjectInfo, 43);

      }

      //순수 명령어 비교.

      else if(STR_Match(prObjectInfo->word, "jump") == true)
      {
        //[OPCODE : 44]
        Object_Opcode(prObjectInfo, 44);

      }
      else if(STR_Match(prObjectInfo->word, "fncall") == true)
      {
        //[OPCODE : 45]
        Object_Opcode(prObjectInfo, 45);

      }
      else if(STR_Match(prObjectInfo->word, "fnstart") == true)
      {
        //[OPCODE : 46]
        Object_Opcode(prObjectInfo, 46);

      }
      else if(STR_Match(prObjectInfo->word, "fnend") == true)
      {
        //[OPCODE : 47]
        Object_Opcode(prObjectInfo, 47);

      }
      else if(STR_Match(prObjectInfo->word, "copy") == true)
      {
        //[OPCODE : 48]
        Object_Opcode(prObjectInfo, 48);

      }
      else if(STR_Match(prObjectInfo->word, "conjt") == true)
      {
        //[OPCODE : 49]
        Object_Opcode(prObjectInfo, 49);

      }
      else if(STR_Match(prObjectInfo->word, "conjf") == true)
      {
        //[OPCODE : 50]
        Object_Opcode(prObjectInfo, 50);

      }
      else if(STR_Match(prObjectInfo->word, "push") == true)
      {
        //[OPCODE : 51]
        Object_Opcode(prObjectInfo, 51);

      }
      else if(STR_Match(prObjectInfo->word, "pop") == true)
      {
        //[OPCODE : 52]
        Object_Opcode(prObjectInfo, 52);

      }
      else if(STR_Match(prObjectInfo->word, "mpush") == true)
      {
        //[OPCODE : 53]
        Object_Opcode(prObjectInfo, 53);

      }
      else if(STR_Match(prObjectInfo->word, "mpop") == true)
      {
        //[OPCODE : 54]
        Object_Opcode(prObjectInfo, 54);

      }
      else if(STR_Match(prObjectInfo->word, "tstart") == true)
      {
        //[OPCODE : 55]
        Object_Opcode(prObjectInfo, 55);

      }
      else if(STR_Match(prObjectInfo->word, "tend") == true)
      {
        //[OPCODE : 56]
        Object_Opcode(prObjectInfo, 56);

      }

      //모두 해당하지 않는 경우.

      else
      {
        //[명령어/연산자] 에 해당하지 않는다.

        //[정보복구]
        //{
            (*prObjectInfo) = objectInfo_Backup;

        //}

        //해당하지 않으므로 여기서 종료한다.
        return(no);

      }
      
  //}

  //[피연산자 처리]
  //{
      //[!]{-------------------------------------------------------------------------------------------
      //[명령어] 는 이미 처리되었으므로 여기서는 모두 공통으로 처리 가능한 [피연산자] 를 처리한다.
      //[ASM 기호] 는 [정보]:[값] 의 형식으로 구성되 있으므로 이를 처리하는 전용 함수로 처리한다.
      //또한, Code 화 된 다음에는 반드시 <LittleEndian> 으로 변환하여 <*.obj> 에 추가해야 한다.
      //
      //[정보] : 2 Byte 고정 크기를 가지고 있으며 이 값은 독립된 값이다.
      //따라서, "[정보 (LittleEndian)][값 (LittleEndian)]" 으로 한덩어리로 만들어 <*.obj> 에 추가한다.
      //
      //단, [함수라벨] 인 경우는 Link() 시 까지 그대로 유지 되어야 하므로 그대로 복사한다.
      //}----------------------------------------------------------------------------------------------

      for(//0st 단어는 이미 처리한 [명령] 이므로 실제 [피연산자] 는 1st 부터 시작된다.
          i = 1;
          ;
          i++)
      {
        //[단어 추출]
        //{
            //현재 지정 순번의 단어를 추출한다.
            Object_GetWord(prObjectInfo, i);

            //추출한 단어가 "" 인 경우는 더이상 이 행에 처리할 단어가 없는 것이다.
            if(prObjectInfo->word[0] == '\0') break;

        //}

        //[함수라벨 인가?]
        //{
            if(prObjectInfo->word[0] == ':')
            {
              //[함수라벨] 의 경우는 그대로 복사한다.

              //[*.obj 에 추가]
              //{
                  //[문자열 code] 자체가 한개의 단어로 되 있으므로 그냥 그대로 추가해 주면 된다.
                  TEMPFILE_Add(prObjectInfo->word); TEMPFILE_Add(" ");

              //}

              //계속 다음 [피연산자] 를 처리한다.
              continue;

            }

        //}

        //[일반 피연산자 처리]
        //{
            //여기까지 온것은 [일반 피연산자] 에 해당한다.
            
            Object_Operand(prObjectInfo->word, code);

            TEMPFILE_Add(code); TEMPFILE_Add(" ");

        //}

      }

      //[*.obj 에 추가]
      //{
          //행을 마무리 한다.
          TEMPFILE_Add("\r\n");

      //}

  //}

  return(yes);

}

int __fastcall Tree_Object_StringCode(struct OBJECTINFO  *prObjectInfo)
{
  //[2009.01.21.수][생성!!!]{---------------------------------------------
  //이 함수가 호출 되는 시점에서는 무조건 [문자열 code] 일수 밖에는 없다.
  //문자열 code 는 무조건 그대로 <*.obj> 에 추가해 주면 된다.
  //}---------------------------------------------------------------------

  //[처리내용]
  //{
      //<*.obj> 에 그대로 무조건 추가 한다.

  //}

  //[첫 단어 추출]
  //{
      //현재 행의 첫 단어를 추출한다.
      Object_GetWord(prObjectInfo, 0);

  //}

  //[*.obj 에 추가]
  //{
      //[문자열 code] 자체가 한개의 단어로 되 있으므로 그냥 그대로 추가해 주면 된다.
      TEMPFILE_Add(prObjectInfo->word); TEMPFILE_Add(" \r\n");

  //}

  return(yes);

}

//[기본 처리 함수]--------------------------------------------------------------

void __fastcall Object_GetWord(//정보구조체.
                               struct OBJECTINFO  *prObjectInfo,
                               //지정 단어 순번(BASE : 0).
                               int    pWordXst)
{
  //[2009.01.12.월][생성!!!]{--------------------------------------------------------------
  //[정보구조체] 를 전달 받아서 현재 정보를 참고하여 해당 순번의 단어를 추출하여 반환한다.
  //현재 행의 시작 index 값등 기본 정보는 전부 [정보구조체] 에 들어 있다.
  //}--------------------------------------------------------------------------------------

  //[단어 추출]
  //{
      //현재 행의 첫 단어를 추출한다.
      STR_GetLineWordBuf(prObjectInfo->ob1Buf,
                         prObjectInfo->lineStartIndex,
                         pWordXst,
                         &(prObjectInfo->wordStartIndex),
                         prObjectInfo->word);

  //}

  return;

}

void __fastcall Object_Opcode(struct OBJECTINFO  *pObjectInfo,
                              int                 pOpcode)
{
  //[2009.01.22.목][생성!!!]{----------------------------------------
  //opcode 값을 전달 받아서 직접 해당 code 를 <*.obj 에 추가해 준다.
  //}----------------------------------------------------------------




  //[VAR]
  //{
      char   hexStr[OPT_1st_symbol_length];
      char   littleEndianStr[OPT_1st_symbol_length];

  //}

  //[Code 구하기]
  //{
      CONV_LongVal_To_Hex(pOpcode, d_VMOS_OpcodeSize*2, hexStr);

  //}

  //[Little Endian 으로 변환]
  //{
      //문자열을 가지고 직접 변환한다.
      Endian_Change_HexStr(hexStr, littleEndianStr);

  //}

  //[*.obj 에 추가]
  //{
      TEMPFILE_Add(littleEndianStr); TEMPFILE_Add(" ");

  //}

  return;

}

void __fastcall Object_OperandType(char            *pTypeSymbol,
                                   unsigned short  *rTypeCode)
{
  //[2009.01.23.금][생성!!!]{-------------------------------------------------
  //[ASM 기호] 에서 [피연산자 정보] 부분의 문자열을 전달 받아서 해당
  //2 Byte Code 로 함성하여 반환한다.
  //
  //ex) i.u.8.c.F.8:ofsAdr
  //    에서 "i.u.8.c.F.8" 부분을 전달 받아서 2 Byte 크기의 Code 로 합성한다.
  //}-------------------------------------------------------------------------

  //[방법]
  //{
      //------------------------------------------------------------------------------------
      // 1bit    1bit     4bit     2bit      4bit       4bit   : 비트수.
      //  15      14     13:10     9:8        7:4       3:0    : 비트영역.
      // [i/f] . [s/u] . [size] . [kind] . [segment] . [byte]  : 이름.
      //------------------------------------------------------------------------------------
      //
      // [i/f]
      //
      // - 정수/실수를 구분한다.
      // - i(0) : 정수.
      //   f(1) : 실수.
      //
      // [s/u]
      //
      // - signed 인지 unsigned 인지 구분한다.
      // - u(0) : unsigned.
      //   s(1) : signed.
      //
      // [size]
      //
      // - 실제 읽어 들일 [크기] 을 가진다(c-type 크기).
      // - 1, 2, 4, 8 로 직접 크기 값을 기술한다(바로 읽어서 사용할수 있도록 하기 위한 것).
      //
      // [kind]
      //
      // - 어떻게 접근할 것인가?
      // - pv(3) : 변수포인터.
      //   cv(2) : 상수포인터.
      //   v (1) : 변수.
      //   c (0) : 상수.
      //
      // [segment]
      //
      // - 참조 대상 기반자.
      // - #(0) : 상수.
      //   R(1) : 레지스터.
      //   C(2) : @CODE.
      //   G(3) : @DATA.
      //   L(4) : @LOCAL.
      //   T(5) : @TEMP.
      //   F(6) : @FUNC.
      //
      // [byte]
      //
      // - [피연산자] 자체 크기로 "i.u.8.c.F.8:ofsAdr" 에서 "ofsAdr" 자체의 크기가 된다.
      // - 1 - 8 사이의 실제 값을 그대로 기술한다.
      //
      //------------------------------------------------------------------------------------

  //}

  //[VAR]
  //{
      char  tempStr[OPT_1st_symbol_length];
      char  hexStr[OPT_1st_symbol_length];
      int   infoCode = 0;
      int   value = 0;

  //}

  //[i/f]
  //{
      //"." 를 구분자로 0st 단어가 해당된다.
      STR_GetWord(pTypeSymbol, '.', 0, tempStr);

      if     (STR_Match(tempStr, "i") == true) { value = 0; }
      else if(STR_Match(tempStr, "f") == true) { value = 1; }

      //[Code 함성]
      //{
          //1bit 크기.
          value &= 0x01;

          //합성.
          infoCode |= (value << 15);

      //}

  //}

  //[s/u]
  //{
      //"." 를 구분자로 1st 단어가 해당된다.
      STR_GetWord(pTypeSymbol, '.', 1, tempStr);

      if     (STR_Match(tempStr, "u") == true) { value = 0; }
      else if(STR_Match(tempStr, "s") == true) { value = 1; }

      //[Code 함성]
      //{
          //1bit 크기.
          value &= 0x01;

          //합성.
          infoCode |= (value << 14);

      //}

  //}

  //[size]
  //{
      //"." 를 구분자로 2st 단어가 해당된다.
      STR_GetWord(pTypeSymbol, '.', 2, tempStr);

      //[16진수 문자열] 로 합성.
      STR_Assign(hexStr, "0x"); STR_Add(hexStr, tempStr);

      //값으로 바꾼다.
      CONV_HexStr_To_IntVal(hexStr, &value);

      //[Code 함성]
      //{
          //4bit 크기.
          value &= 0x0f;

          //합성.
          infoCode |= (value << 10);

      //}

  //}

  //[kind]
  //{
      //"." 를 구분자로 3st 단어가 해당된다.
      STR_GetWord(pTypeSymbol, '.', 3, tempStr);

      if     (STR_Match(tempStr, "pv") == true) { value = 3; }
      else if(STR_Match(tempStr, "pc") == true) { value = 2; }
      else if(STR_Match(tempStr, "v")  == true) { value = 1; }
      else if(STR_Match(tempStr, "c")  == true) { value = 0; }

      //[Code 함성]
      //{
          //2bit 크기.
          value &= 0x03;

          //합성.
          infoCode |= (value << 8);

      //}

  //}

  //[segment]
  //{
      //"." 를 구분자로 3st 단어가 해당된다.
      STR_GetWord(pTypeSymbol, '.', 4, tempStr);

      if     (STR_Match_NoCase(tempStr, "#") == true) { value = 0; }
      else if(STR_Match_NoCase(tempStr, "R") == true) { value = 1; }
      else if(STR_Match_NoCase(tempStr, "C") == true) { value = 2; }
      else if(STR_Match_NoCase(tempStr, "G") == true) { value = 3; }
      else if(STR_Match_NoCase(tempStr, "L") == true) { value = 4; }
      else if(STR_Match_NoCase(tempStr, "T") == true) { value = 5; }
      else if(STR_Match_NoCase(tempStr, "F") == true) { value = 6; }

      //[Code 함성]
      //{
          //4bit 크기.
          value &= 0x0f;

          //합성.
          infoCode |= (value << 4);

      //}

  //}

  //[byte]
  //{
      //"." 를 구분자로 5st 단어가 해당된다.
      STR_GetWord(pTypeSymbol, '.', 5, tempStr);

      //[16진수 문자열] 로 합성.
      STR_Assign(hexStr, "0x"); STR_Add(hexStr, tempStr);

      //값으로 바꾼다.
      CONV_HexStr_To_IntVal(hexStr, &value);

      //[Code 함성]
      //{
          //4bit 크기.
          value &= 0x0f;

          //합성.
          infoCode |= (value << 0);

      //}

  //}

  //[반환]
  //{
      //[합성] 한 2 Byte Code 를 반환한다.
      (*rTypeCode) = infoCode;

  //}      

  return;

}

void __fastcall Object_Operand(char  *pAsmSymbol,
                               char  *rCode)
{
  //[2009.01.23.금][생성!!!]{-----------------------------------------------------------------
  //[피연산자] 를 Code 로 변환한다.
  //"[정보]:[값]" 으로 이루어진 [ASM 기호] 를 분석해서 직접 <Little Endian> code 로
  //변환하여 <*.obj> 에 추가해준다.
  //이 함수는 순수하게 [일반 피연산자] 만을 대상으로 하고 [함수라벨] 은 대상으로 하지 않는다.
  //처리 대상이 되는 단어는 이미 pObjectInfo->Word[] 에 들어 있다.
  //Code 는 한개의 [피연산자] 이므로 한 덩어리로 붙여주어야 한다.
  //}-----------------------------------------------------------------------------------------

  //[VAR]
  //{
      char   opndInfoWord[OPT_wordStrSize];

      char   opndDataWord[OPT_wordStrSize];

      char   tempWord[OPT_wordStrSize];

      char   littleEndianStr[OPT_1st_symbol_length];

      unsigned short  infoCode;

  //}

  //[단어 구분]
  //{
      //각각의 단어는 ":" 문자로 간단하게 구분 할수 있다.

      //[정보 부분 얻기]
      //{
          //":" 를 [구분자] 로 0st 단어가 [정보] 에 해당한다.
          STR_GetWord(pAsmSymbol, ':', 0, opndInfoWord);

      //}

      //[정보 부분 얻기]
      //{
          //":" 를 [구분자] 로 0st 단어가 [정보] 에 해당한다.
          STR_GetWord(pAsmSymbol, ':', 1, opndDataWord);

      //}

  //}

  //[정보 처리]
  //{
      //[정보] 를 2 Byte 의 해당 Code 로 변환한다.

      //실제 2 Byte 값으로 얻는다.
      Object_OperandType(opndInfoWord, &infoCode);

      //일단 16진수 4 Digit 의 [문자열] 로 변환한다.
      CONV_LongVal_To_Hex(infoCode, 4, tempWord);

      //[Little Endian 으로 변환]
      //{
          //[문자열] 을 가지고 직접 변환한다.
          Endian_Change_HexStr(tempWord, littleEndianStr);

      //}

      //[<*.obj> 에 추가]
      //{
          STR_Assign(rCode, littleEndianStr);

      //}

  //}

  //[값 처리]
  //{
      //[값] 부분은 이미 16진수 문자열로 처리되 있으므로 그대로 읽어서 <Little Endian> 로
      //변환해 준다음 바로 <*.obj> 에 추가해 주면 된다.

      //[Little Endian 으로 변환]
      //{
          //문자열을 가지고 직접 변환한다.
          Endian_Change_HexStr(opndDataWord, littleEndianStr);

      //}

      //[<*.obj> 에 추가]
      //{
          STR_Add(rCode, littleEndianStr);

      //}

  //}

  return;

}
