(*~\Глагол\ПриложенияLink\ПГ\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                              ОТДЕЛ ЗП;
(*============================================================================*)
(* НАЗНАЧЕНИЕ: Запускает Преобразователь                                      *)
(*============================================================================*)

ИСПОЛЬЗУЕТ
        (*  \Глагол\                    *)
 оЦепи    ИЗ "..\..\Отделы\Иное\",
  Пустой  ИЗ "..\..\Отделы\Иное\",
ЧэргаСлеД ИЗ "..\..\Отделы\Иное\",
        (*  \Глагол\                    *)
  ОС      ИЗ "..\..\Отделы\Обмен\",
    Файл  ИЗ "..\..\Отделы\Обмен\",
   ВФайл  ИЗ "..\..\Отделы\Обмен\ВводВывод\",
  НаЭкран ИЗ "..\..\Отделы\Обмен\ВводВывод\",

  НП,ОО,ФО,ВД,РС,РВ,ПД,Coff,ЗК,CV,ОД,КУ,СК,ПЗ;

ВИД
  ДкФайлуОтдела = ДОСТУП К (*нФайлОтдела;
                             нФайлОтдела =*) НАБОР(ЧэргаСлеД.нПустой)
    имя  :НП.Имя;
    имяФ :Пустой.ДкЦепи; (* :ДОСТУП К ЦЕПЬ; *)
    время:Файл.шцВремя
                                             КОН;
(*---
                       набор-список отделов на обработку
  ---*)
ПЕР
  отдCПредками,                       (* список отделов с известными предками *)
  отдНаОбработку :ЧэргаСлеД.нСписок;  (* список отделов на обработку          *)



(*-оооооооооооооо- опережающие определения/заготовки задач -ооооооооооооооооо-*)

ЗАДАЧА ^ЗаписатьПринимаемыеЗадачи;


(*=рррррррррррррррррррррррр= реализация задач =рррррррррррррррррррррррррррррр=*)


(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА НайтиПредков(отдМесто-:ЦЕПЬ;
                    отдИмя-  :НП.Имя):ДкФайлуОтдела;
(*
 * Цель:  или находит <отделД> в списке <отдCПредками> или создает новый <отделД>,
 *        находит его предков и включает его в список <отдCПредками>
 * До:    <отдМесто> - местоположение файла данного отдела
 *        <отдИмя>   - имя данного отдела
 * Ответ: <ДкФайлуОтдела> - доступ к файлу отдела с предками
 *)
ПЕР
      звеноД:ЧэргаСлеД.ДкЗвену_телоД;
    испИмена:ЧэргаСлеД.нСписок;             (* список испИмена *)

    испИмяД :РВ.ДкИспИмя;  (* доступ к звену в списке испИмена *)
    испМесто:Файл.ВПути;

   предокД,
    отделД  :ДкФайлуОтдела;

  времяПредков:Файл.шцВремя;
     отдИмяФ  :Файл.ВПолного;
УКАЗ
  Файл.СобратьИмя(отдИмяФ,отдМесто,отдИмя,"отд");
(*
    может <отделД> уже есть в очереди <отдCПредками>
*)
      звеноД:=ЧэргаСлеД.Дк1муЗвену(отдCПредками);
  ПОКА
      звеноД # ПУСТО
  ВЫП                                                          (* преобразование полиморфное  
                       телоД               из ЧэргаСлеД.ДкПустомуНабору 
                             ДкФайлуОтдела <- ЧэргаСлеД.ДкПустомуНабору                   *)
        отделД:=звеноД.телоД(ДкФайлуОтдела);
    ЕСЛИ
        отделД.имяФ^ = отдИмяФ
    ТО
      ЕСЛИ
        отделД.время = МИН(Файл.шцВремя)
      ТО
        ОО.Ошибка(ОО.ПЕРЕКРЕСТНОЕ_ИСПОЛЬЗОВАНИЕ)
      КОН;
      ВОЗВРАТ отделД
    КОН;
    звеноД:=звеноД.слеД
  КОН;
          (* создаём и запоминаем новый <отделД> - доступ к телу звена-отдела *)
  ЕСЛИ
      НЕ Файл.Существует(отдИмяФ)
  ТО
    ОО.Отметить(ОО.ФАЙЛ_НЕ_ОТКРЫВАЕТСЯ,отдИмяФ)
  КОН;
  СОЗДАТЬ(отделД);
  СПИСАТЬ(отдИмя,отделД.имя);
  СОЗДАТЬ(отделД.имяФ,отдИмяФ);
                               (* для обнаружения перекрестного использования *)
  отделД.время:=МИН(Файл.шцВремя);

   (* создаём новое <звеноД> (с доступом к телоД=отделД) внутри задачи ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(..)
                                                            и присоединяем это звено к концу списка звеньев *)
  ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(отдCПредками,отделД);

                                               (* смотрим используемые отделы *)
  ФО.УстОтдИмяФ(отдИмяФ);
  РС.Подготовить;
  РВ.Подготовить;
  РВ.НайтиИспИмена(отдИмя,испИмена);
  времяПредков:=МИН(Файл.шцВремя);
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
               звеноД:=ЧэргаСлеД.Дк1муЗвену(испИмена);
  ПОКА
               звеноД # ПУСТО
  ВЫП                                                      (* преобразование  
                      телоД             из ЧэргаСлеД.ДкПустомуНабору 
                            РВ.ДкИспИмя <- ЧэргаСлеД.ДкПустомуНабору          *)
      испИмяД:=звеноД.телоД(РВ.ДкИспИмя);

                          ОО.текПоз:=испИмяД.поз;
            Файл.НайтиМесто(отдМесто,испИмяД.путь^,испМесто);
      предокД:=НайтиПредков(испМесто,испИмяД.имя);
                                                 (* возвращаем в ФО "отдИмяФ" *)
    ФО.УстОтдИмяФ(отдИмяФ);
    ЕСЛИ
        предокД.время > времяПредков
    ТО                                             (* наибольшее время предка *)
      времяПредков:=предокД.время
    КОН;
               звеноД:=звеноД.слеД
  КОН;

  ЕСЛИ
      ФО.НужнаОбр(времяПредков)
  ТО
    отделД.время:=МАКС(Файл.шцВремя);

    ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(отдНаОбработку,отделД)
  ИНАЧЕ
    Файл.ВремяИзменения(ФО.опгИмяФ,отделД.время)
  КОН;

  ВОЗВРАТ отделД
КОН НайтиПредков;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ОшибкуНаЭкранСТОП1(строка,
                         колонка:ЦЕЛ; текст-:ЦЕПЬ);
УКАЗ
       НаЭкран.ВсяЦепь(ФО.отдИмяФ);                       (* имя файла-отдела *)
       НаЭкран.Цел4числа(" (%d:%d) - ",строка,колонка,0,0);(* позиция в файле *)
       НаЭкран.ВсяЦепь(текст);                   (* текст сообщения об ошибке *)
       НаЭкран.ВсяЦепь(".^");           (* тчк и переход на новую строку - ВК *)

  ФО.УдалитьКод;
  СТОП(1)
КОН ОшибкуНаЭкранСТОП1;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ПреобразоватьОтдел;
ПЕР
  задачи:ПД.ДкУзлу;
УКАЗ
    ВД.Подготовить;
    ВД.ОткрытьОбласть(0);
    РС.Подготовить;
    ПЗ.Подготовить;
    РВ.Подготовить;
    РВ.Отдел(задачи);
    ФО.УдалитьКод;

  Coff.Подготовить;
    ЗК.Подготовить;

  ОД.AdrAndSize;
  ЕСЛИ
       НП.отдВид # НП.приложение
  ТО
    ВД.Сохранить
  КОН;
  ЕСЛИ
       НП.отдВид # НП.описание
  ТО
    ЕСЛИ НП.отдВид = НП.приложение ТО
      ЗаписатьПринимаемыеЗадачи
    КОН;
    ФО.КодОткрыть;
    КУ.Подготовить;
    ОД.Module(задачи);
    ЗК.OutCode;
    ФО.КодЗакрыть
  КОН;
    ЗК.Завершить;
    ПЗ.Завершить;
  Coff.Завершить;
    ВД.ЗакрытьОбласть;
    ВД.Завершить
КОН ПреобразоватьОтдел;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЗаписатьСписокОтделов;
    (* Запись в файл "Otdely.spi" списка всех используемых .obj файлов *)
ПЕР
  звеноД:ЧэргаСлеД.ДкЗвену_телоД;
  отделД:ДкФайлуОтдела;
  потокД:ВФайл.ДкПотоку;
 кодИмяФ: Файл.ВПолного;
    путь: Файл.ВПути;
     имя:НП.Имя;
     тип: Файл.ВТипа;
УКАЗ
       потокД:=ВФайл.Открыть("Otdely.spi");
  ЕСЛИ
       потокД = ПУСТО
  ТО
    ОО.Отметить(ОО.ФАЙЛ_НЕ_ОТКРЫВАЕТСЯ,"Otdely.spi")
  КОН;
       потокД.цВидЗнаков:=ВФайл.знВин;

       звеноД:=ЧэргаСлеД.Дк1муЗвену(отдCПредками);
  ПОКА
       звеноД # ПУСТО
  ВЫП                                                      (* преобразование  
                   телоД               из ЧэргаСлеД.ДкПустомуНабору 
                         ДкФайлуОтдела <- ЧэргаСлеД.ДкПустомуНабору           *)
    отделД:=звеноД.телоД(ДкФайлуОтдела);
         (*
            При компиляции ПГ0->ПГ1, ПГ1->ПГ2 (2009.03.11 или 2009.08.15) срабатывает ловушка:
    отделД:=звеноД.телоД(ДкФайлуОтдела) = ПУСТО
          *)

    Файл.РазобратьИмя(отделД.имяФ^,путь,имя,тип);
   оЦепи.ДобавитьВКонец(путь,"Код\");                                  
    Файл.СобратьИмя(кодИмяФ,путь,имя,"obj^");
   ВФайл.ЦепьЗнаков(потокД,кодИмяФ);

    звеноД:=звеноД.слеД
  КОН;
  ВФайл.Закрыть(потокД)
КОН ЗаписатьСписокОтделов;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЗаписатьПринимаемыеЗадачи;
    (* Запись в особые файлы списков принимаемых передаваемых задач *)
УКАЗ
  ЕСЛИ
      НП.клКодДляМСборки
  ТО
    ПЗ.ПерЗадачиДляMSLink;
    ПЗ.ПринЗадачиДляMSLink
  ИНАЧЕ
    ПЗ.ПерЗадачиДляALink;
    ПЗ.ПринЗадачиДляALink
  КОН
КОН ЗаписатьПринимаемыеЗадачи;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА ПреобрОтделы-(отдИмяФ-,
                     срдПуть-:ЦЕПЬ; настройки:МНОЖ;
                                         свод:ЦЕЛ);
(*
 * Цель:  преобразовать текст данного отдела и всех обновлённых отделов,
 *        которые он использует (явно и неявно) в машинный код
 * До:    <отдИмяФ>   - относительное имя файла преобразуемого отдела
 *        <срдПуть>   - путь к СРЕДА.отд
 *        <настройки> - множество ключей преобразования
 *        <свод>      - свод настроек
 * После: *.опг       - общедоступные понятия каждого отдела 
 *        *.obj       - машинный код в формате COFF для каждого отдела
 *)
ПЕР
  звеноД:ЧэргаСлеД.ДкЗвену_телоД;
  отделД:ДкФайлуОтдела;
  местоФ:Файл.ВПолного;
  место :Файл.ВПути;
     имя:НП.Имя;
     тип:Файл.ВТипа;
УКАЗ
  ЧэргаСлеД.ОчиститьСписок(отдCПредками);
  ЧэргаСлеД.ОчиститьСписок(отдНаОбработку);
  ФО.Подготовить;
  НП.Подготовить(настройки,свод);

  ОО.Подготовить(ОшибкуНаЭкранСТОП1);

  ОС.МестоФ(срдПуть,место);
  ЕСЛИ
      место[ДЛИНА(место)-1] # "\"
  ТО
    оЦепи.ДобавитьВКонецЗнак(место,"\")
  КОН;
  РВ.УстСрдМесто(место);

    ОС.МестоФ(отдИмяФ,местоФ);                                  
  Файл.РазобратьИмя(местоФ,место,имя,тип);

    отделД:=НайтиПредков(место,имя);
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
       звеноД:=ЧэргаСлеД.Дк1муЗвену(отдНаОбработку);
  ПОКА
       звеноД # ПУСТО
  ВЫП                                                      (* преобразование  
                   телоД               из ЧэргаСлеД.ДкПустомуНабору 
                         ДкФайлуОтдела <- ЧэргаСлеД.ДкПустомуНабору           *)
    отделД:=звеноД.телоД(ДкФайлуОтдела);

    НаЭкран.ВсяЦепь(отделД.имяФ^);
    НаЭкран.ВсяЦепь("^");
    ФО.УстОтдИмяФ(отделД.имяФ^);

    ПреобразоватьОтдел;

       звеноД:=звеноД.слеД
  КОН;
  ЗаписатьСписокОтделов;

  ЧэргаСлеД.ОчиститьСписок(отдНаОбработку);
  ЧэргаСлеД.ОчиститьСписок(отдCПредками)
КОН ПреобрОтделы;

КОН ЗП.
