word
  Seg_Cfg;              // Сегмент для чтения файла конфигурации
word
  Cfg_Size,             // Размер буфера файла конфигурации
  Cfg_Pos,              // Текущая позиция в буффере
  Cfg_Str;              // Номер строки в файле конфигурации
word
  CRKbegin,             // Смещение заголовка CRK в буфере
  CRKsize,              //   - его размер
  XCKbegin,             // Смещение заголовка XCK в буфере
  XCKsize1,             //   - его размер
  XCKend,               // Смещение хвоста XCK в буфере
  XCKsize2;             //   - его размер

byte
  OutFileFormat;        // Формат выходного файла: 0 - CRK    1 - XCK

char
  ConfigFileName   = "CMP.CFG",
  cfgOutFileName   = "OutFileName",
  cfgOutFileFormat = "OutFileFormat",
  cfgCRK           = "CRK",
  cfgXCK           = "XCK",
  cfgCRKbegin      = "[CRK]",
  cfgXCKbegin      = "[XCKbegin]",
  cfgXCKend        = "[XCKend]",
  cfgEnd           = "[end]",
  cfgMmode         = "%MODE%",
  cfgMdate         = "%DATE%",
  cfgMtime         = "%TIME%",
  cfgMfile1        = "%FILE1%",
  cfgMfile2        = "%FILE2%",
  cfgMfilename1    = "%FILENAME1%",
  cfgMfilename2    = "%FILENAME2%",
  cfgMname1        = "%NAME1%",
  cfgMname2        = "%NAME2%",
  cfgMsize1        = "%SIZE1%",
  cfgMsize2        = "%SIZE2%";
//-------------------- Чтение файла конфигурации ----------------------------
inline void fastcall LoadConfig()
{
  word ConfigFile;

  ConfigLoaded = FALSE;
  StrCpy(#str, #StartPathStr);
  @StrCat(#ConfigFileName);
  ConfigFile = OpenFile(#str);
  Cfg_Size = GetFileSize(AX);

  IF (EAX > 0xFFFE)
    {
      WriteStr(#strError4);
      RETURN;
    }
  IF ( GETMEM( 0x1000 ) == 0 )
    {
       WriteStr(#strError3);
       RETURN;
    }
  ELSE Seg_Cfg = AX;
  ReadFile_FAR(ConfigFile, AX, Cfg_Size);
  CloseFile(ConfigFile);
  ConfigLoaded = TRUE;
}
//---------------------- Выдать сообщение о ошибке --------------------------
void fastcall ConfigError()
{
  StrCpy(#str, #strError5);
  LongToStr(Cfg_Str);
  @StrAddByte(0);
  WriteStr(#str);
  ErrorStatus = TRUE;
}
//------------------------ Читать строку из буффера -------------------------
byte fastcall ReadlnBuf(DI)
{
  DX = Cfg_Size;
  SI = Cfg_Pos;
  IF (SI >= DX)  RETURN FALSE;
  $PUSH   DS
  DS =  Seg_Cfg;
  do
    {
      $LODSB
      $STOSB
    } while ((AL != 0x0D) && (SI <= DX));

  $POP    DS
  DI --;
  @StrAddByte(0);
  Cfg_Pos = SI + 1;
  Cfg_Str ++;
  RETURN TRUE;
}
//----------------- Читает строку вида Param = Val --------------------------
// DI <- Val
byte fastcall ReadCfgStr()
{
  IF (!ReadlnBuf(#str))  RETURN  -1;               // конец буффеpа
  StrFind(";", #str);
  IF (DI != 0xFFFF)  @StrAddByte(0);

  StrTrim(#str);
  StrLen(#str);
  IF (CX == 0)  RETURN 3;                         // пустая стpока

  StrFind("=", #str);
  IF (DI != 0xFFFF)
    {
      @StrAddByte(0);
      $PUSH   DI
      StrTrim(DI);
      StrTrimEnd(#str, #str);
      $POP    DI
      RETURN 1;                                   // Hашли !
    }
  RETURN 2;                                       // Hе то (ошибка ?)
}
//---------------------- Получить строковой параметр ------------------------
void fastcall GetStr(SI, DI)
{
  IF (LoadByte() != 0x27)  GOTO Err;           // "'"
  do
     {
       BL = AL;
       $LODSB
       $STOSB
     } while (AL != 0);
  IF (BL != 0x27) GOTO Err;
  DI -= 2;
  @StrAddByte(0);
  RETURN;
Err:
  ConfigError();
}
//------------------ Подстановка одного макpоопpеделения --------------------
void InitMacro(char *str1, *str2)
{
  int W;

  StrLen(str1);
  BX = CX;
  StrLen(str2);
  W = CX - BX;
  WHILE (StrReplace(Seg_Cfg, 0, DS, str1, DS, str2))      Cfg_Size += W;
}
//------------------- Подстановка всех макpоопpеделений ---------------------
inline void InitAllMacros()
{
  IF (OutFileFormat == 0)  InitMacro(#cfgMmode, #cfgCRK);
  ELSE IF (OutFileFormat == 1)  InitMacro(#cfgMmode, #cfgXCK);     // %MODE%

  StrDate(#str);
  InitMacro(#cfgMdate, #str);                                      // %DATE%

  StrTime(#str);
  InitMacro(#cfgMtime, #str);                                      // %TIME%

  InitMacro(#cfgMfile1, #FileName[0]);                             // %FILE1%
  InitMacro(#cfgMfile2, #FileName[MAX_PATH_LENGTH]);               // %FILE1%

  DI = #str;
  JustFileName(#FileName[0]);
  InitMacro(#cfgMfilename1, #str);                                 // %FILENAME1%
  DI = #str;
  JustFileName(#FileName[MAX_PATH_LENGTH]);
  InitMacro(#cfgMfilename2, #str);                                 // %FILENAME2%

  DI = #str;
  JustName(#FileName[0]);
  InitMacro(#cfgMname1, #str);                                     // %NAME1%
  DI = #str;
  JustName(#FileName[MAX_PATH_LENGTH]);
  InitMacro(#cfgMname2, #str);                                     // %NAME2%


  DI = #str;
  File[0] = OpenFile(#FileName[0]);
  GetFileSize(AX);
  Long_To_Str();
  @StrAddByte(0);
  CloseFile(File[0]);
  InitMacro(#cfgMsize1, #str);                                     // %SIZE1%

  DI = #str;
  File[2] = OpenFile(#FileName[MAX_PATH_LENGTH]);
  GetFileSize(AX);
  Long_To_Str(EAX);
  @StrAddByte(0);
  CloseFile(File[2]);
  InitMacro(#cfgMsize2, #str);                                     // %SIZE2%
}
//-------------------------- Загрузка конфигурации --------------------------
void LoadFile()
{
  word Param, W;

  Cfg_Str = 0;
  Cfg_Pos = 0;

  CRKsize = XCKsize1 = XCKsize2 = 0;
  while (ReadCfgStr() != -1)
    {
      IF (AL == 1)
        {
          Param = DI;
          IF (StrCmp(#cfgOutFileName, #str))                    // OutFileName
            {
              GetStr(Param, #str);
              StrCpy(#FileName_Out, #str);
              continue;
            }
          ELSE IF (StrCmp(#cfgOutFileFormat, #str))           // OutFileFormat
            {
              IF (StrCmp(Param, #cfgCRK))  OutFileFormat = 0;
              ELSE IF (StrCmp(Param, #cfgXCK))  OutFileFormat = 1;
              ELSE ConfigError();
            }
          ELSE ConfigError();
        }
      else if (AL == 2)
        {
          IF (StrCmp(#cfgCRKbegin, #str))                // [CRK]
            {
              CRKbegin = Cfg_Pos;
              WHILE (!StrCmp(#cfgEnd, #str))
                {
                  W = Cfg_Pos;
                  IF (!ReadlnBuf(#str))
                    {
                       ConfigError();
                       BREAK;
                    }
                  StrTrim(#str);
                }
              CRKsize = W - CRKbegin - 2;
            }
          else IF (StrCmp(#cfgXCKbegin, #str))           // [XCKbegin]
            {
              XCKbegin = Cfg_Pos;
              WHILE (!StrCmp(#cfgEnd, #str))
                {
                  W = Cfg_Pos;
                  IF (!ReadlnBuf(#str))
                    {
                       ConfigError();
                       BREAK;
                    }
                  StrTrim(#str);
                }
              XCKsize1 = W - XCKbegin - 2;
            }
          ELSE IF (StrCmp(#cfgXCKend, #str))           // [XCKend]
            {
              XCKend = Cfg_Pos;
              WHILE (!StrCmp(#cfgEnd, #str))
                {
                  W = Cfg_Pos;
                  IF (!ReadlnBuf(#str))
                    {
                       ConfigError();
                       BREAK;
                    }
                  StrTrim(#str);
                }
              XCKsize2 = W - XCKend - 2;
            }
          ELSE ConfigError();
        }
      ELSE IF (AL == 3) CONTINUE;                       // пустая стpока
    }
}
//------------------------ Загрузка конфигурации ----------------------------
inline void LoadConfiguration()
{
  LoadConfig();
  IF (!ConfigLoaded) RETURN;
  LoadFile();
  InitAllMacros();
  IF (!ErrorStatus)  LoadFile();
}
//---------------------------------------------------------------------------