
 
 
 


      Mинистерство приборостроения, средств автоматизации
 
                      и систем управления
 
 
 
 
 
 
 
 
 
                  Oперационная система МОС ВП
 
              Подсистема системного программиста
 
                      МОДУЛЬНЫЕ ПРОЦЕДУРЫ
 
                      Cправочный материал
 
 
 
 
                       Лист утверждения
 
                    2б.00152-01 97 08-ЛУ
 
                           Листов 2
 
 
                                  Pуководитель темы,
 
                                  зам. директора ИНЭУМ
 
                                  _______________ Xрущев C.H.
 
                                  "___"__________ 1987 г.
 
                     Представители предприятия-разработчика:
 
                                  зав. oтделом BCKTБ
 
                                  _____________ Hахмансон B.C
 
                                  "___"________ 1987 г.
 
                                  Зам.зав.отделом BCKTБ
 
                                  _____________ Mихайлов B.C.
 
                                  "___"________ 1987 г.
 
 
                             1987
 
     Перв. примен.                                  Литера O
      2б.00152-01
 
 


                            - 2 -
 
 
                    2б.00152-01 97 08-ЛУ
 
 
 
 
 
 
                       Представители ИНЭУМ:
 
 
                               Oтветственный исполнитель темы
 
                               Зав. oтделением
 
                               -------------- Oстапенко Г.П.
 
                               "---"--------- 1987 г.
 
                                Нормоконтролер
 
                                --------------
 
                                "---"--------- 1987 г.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


     
     
     
     
         Утвержден
     
        2б.00152-01 97 08-ЛУ
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
                      Операционная система МОС ВП
     
                    Подсистема разработки программ
     
                          МОДУЛЬНЫЕ ПРОЦЕДУРЫ
     
                          Справочный материал
     
     
                          2б.00152-01 97 08
     
                             Листов 217/5K
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
                                 1987
     
     
         Перв. примен.                         Литера O
         2б.00152-01
     
    
    


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                      Операционная система МОС ВП
 
                    Подсистема разработки программ
 
                          МОДУЛЬНЫЕ ПРОЦЕДУРЫ
 
                          Справочный материал
 
                            00152-01 97 08
 
                              Листов 212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                                 1987
 
 
 
 
 
 


                                - 2 -
 
                           00152-01 97 08
 
 
 
 
 
 
                              АННОТАЦИЯ
 
 
 
 
 
           Настоящий  документ  предназначен  для   разработчиков
 
      модульных процедур системы МОС ВП.
 
           Документ содержит описание правил модульного  програм-
 
      мирования,     охватывающих      этапы      проектирования,
 
      кодирования,тестирования, об'единения в библиотеки и сопро-
 
      вождения создаваемых процедур.
 
           Следование  обязательным  и   рекомендуемым   правилам
 
      модульного  программирования  сокращает  время   разработки
 
      программного обеспечения, повышает надежность,  удобочитае-
 
      мость программ, облегчает и удешевляет их сопровождение.
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 3 -
 
                           00152-01 97 08
 
 
 
 
 
 
                              СОДЕРЖАНИЕ
 
 
 
 
 
      1.  Введение в модульные процедуры                      10
 
      1.1.  Жизненный цикл программного обеспечения           10
 
      1.2.  Определение модульной процедуры                   11
 
      1.3.  Процедуры системы МОС ВП                          14
 
      1.3.1.  Процедуры исполнительной библиотеки             16
 
      1.3.2.  Программы системного обслуживания               20
 
      1.3.3.  Обслуживающие программы                         25
 
      1.3.4.  Система управления данными СУД-32               28
 
      1.4.  Средства   разработки   прикладного   программного
 
            обеспечения в МОС ВП                              29
 
 
 
      2.  Проектирование                                      31
 
      2.1.  Организация разрабатываемых прикладных программ   31
 
      2.1.1.  Организация файлов и модулей                    32
 
      2.1.2.  Организация процедур внутри модулей             32
 
      2.2.  Описание интерфейса модульной процедуры           38
 
      2.2.1.  Явные параметры                                 38
 
      2.2.2.  Неявные параметры                               39
 
      2.2.2.1.  Неявные параметры,  распределяемые  вызывающей
 
                программой                                    39
 
      2.2.2.2.  Неявные  параметры,  распределяемые  вызванной
 
                процедурой                                    40
 
      2.2.3.  Обход использования неявных параметров          41
 
      2.2.3.1.  Об'единение процедур                          42
 
      2.2.3.2.  Пользовательская программа развязки           45


                                - 4 -
 
                           00152-01 97 08
 
 
 
      2.2.3.3.  Возложение функций  сохранения  информации  на
 
                вызывающую программу                          45
 
      2.2.3.4.  Выделение    памяти    процедуре    вызывающей
 
                программой                                    48
 
      2.2.3.5.  Передача вызывающей программой указателя      48
 
      2.2.3.6.  Передача вызывающей программой идентификатора,
 
                имеющего смысл в рамках процесса              50
 
      2.2.4.  Порядок расположения параметров                 51
 
      2.2.5.  Использование необязательных параметров         52
 
      2.3.  Входные точки JSB                                 53
 
      2.4.  Использование ресурсов системы                    54
 
      2.4.1.  Выбор типа памяти                               54
 
      2.4.1.1.  Стековая память                               54
 
      2.4.1.2.  Массовая память                               55
 
      2.4.1.3.  Статическая память                            55
 
      2.4.1.4.  Обход использования статической памяти        56
 
      2.4.1.5.  Обзор используемых в  языках  программирования
 
                способов хранения информации                  58
 
      2.4.2.  Использование флагов событий                    60
 
      2.4.3.  Использование номеров логических устройств      60
 
      2.5.  Использование ввода-вывода                        60
 
      2.5.1.  Ввод-вывод с терминала                          61
 
      2.5.2.  Ввод-вывод из файла                             64
 
      2.6.  Документирование                                  65
 
      2.6.1.  Описание модуля                                 65
 
      2.6.2.  Описание процедуры                              67
 
      2.7.  Планирование сигнализации и обработки условий     70
 
      2.7.1.  Основные положения по сигнализации  об  условиях
 
              ошибок                                          71
 


                                - 5 -
 
                           00152-01 97 08
 
 
      2.7.2.  Основные положения для возвращаемых значений    72
 
      2.7.3.  Выставление   сигналов   и   возврат    значений
 
              исключительного состояния                       73
 
 
 
      3.  Кодирование                                         75
 
      3.1.  Основные положения по кодированию                 75
 
      3.1.1.  Написание   позиционно   -   независимого   кода
 
              (обязательное)                                  75
 
      3.1.2.  Принятые соглашения по наименованиям            76
 
      3.1.2.1.  Соглашения     по     наименованию     средств
 
                (рекомендуемые)                               76
 
      3.1.2.2.  Соглашения    по     наименованию     процедур
 
                (рекомендуемые)                               79
 
      3.1.2.3.  Соглашения     по     наименованию      файлов
 
                (рекомендуемые)                               81
 
      3.1.2.4.  Соглашения     по     наименованию     модулей
 
                (обязательные)                                82
 
      3.1.2.5.  Соглашения по наименованию программных  секций
 
                (PSECT) (обязательные)                        82
 
      3.1.2.6.  Соглашения  по   наименованию   блокированного
 
                ресурса (рекомендуемые)                       83
 
      3.1.2.7.  Соглашения    по    наименованию    глобальной
 
                переменной (рекомендуемые)                    83
 
      3.1.2.8.  Соглашения по наименованию  кода  состояния  и
 
                значения       исключительного       состояния
 
                (обязательные)                                85
 
      3.1.3.  Использование     общих     исходных      файлов
 
              (рекомендуемые)                                 86
 
      3.1.4.  Обеспечение удобочитаемости программ            88
 
      3.1.4.1.  Использование  символьных  обозначений  вместо


                                - 6 -
 
                           00152-01 97 08
 
 
 
                чисел (рекомендуется)                         88
 
      3.1.4.2.  Использование  знаков   верхнего   и   нижнего
 
                регистров (рекомендуется)                     90
 
      3.1.4.3.  Добавление       необязательных       пробелов
 
                (рекомендуется)                               91
 
      3.1.4.4.  Вставка блока комментариев (рекомендуется)    92
 
      3.1.5.  Использование  средств  системного  обслуживания
 
              системы МОС ВП                                  93

      3.1.6.  Вызов необязательных  пользовательских  программ
 
              развязки                                        93
 
      3.1.6.1.  Маска точки входа процедуры                   94
 
      3.1.6.2.  Связанное с процедурой значение               95
 
      3.2.  Инициализация модульных процедур                  96
 
      3.2.1.  Инициализация памяти                            100
 
      3.2.2.  Проверка и установка флага первого входа        102
 
      3.2.3.  Использование LIB$INITIALIZE                    106
 
      3.3.  Написание программы, реентерабельной по AST       109
 
      3.3.1.  Определение асинхронного системного прерывания  110
 
      3.3.2.  Реентерабельность    по     AST     и     полная
                                                              
              реентерабельность                               112
 
      3.3.3.  Основные  положения   по   написанию   модульных
                          
              процедур, рeeнтерабельных по AST                113
 
      3.3.4.  Ликвидация     условий     соперничества     при
 
              параллельном доступе                            115
 
      3.3.4.1.  Выполнение операций доступа посредством  одной
 
                инструкции                                    117
 
      3.3.4.2.  Использование    инструкций    "проверить    и
 
                установить"                                   119
 
      3.3.4.3.  Обслуживание    счетчика    текущих    вызовов
 


                                - 7 -
 
                           00152-01 97 08
 
 
                программы                                     122
 
      3.3.4.4.  Блокирование асинхронных системных прерываний 122
 
      3.3.5.  Выполнение  операций  ввода-вывода   на   уровне
 
              асинхронных системных прерываний                124
 
      3.3.6.  Обработка   условий   на   уровне    асинхронных
 
              системных прерываний                            126
 
 
 
      4.  Тестирование                                        127
 
      4.1.  Тестирование отдельных блоков процедуры           128
 
      4.1.1.  Тестирование "черного ящика"                    130
 
      4.1.2.  Тестирование "белого ящика"                     131
 
      4.2.  Проверка    на     независимость     от     языков
 
            программирования                                  133
 
      4.3.  Об'единенное тестирование                         134
 
      4.3.1.  Подход "все сразу" в об'единенном тестировании  135
 
      4.3.2.  Подход с нарастанием в об'единенном тестировании136
 
      4.4.  Тестирование на реентерабельность                 138
 
      4.4.1.  Проверка реентерабельности по AST               138
 
      4.4.1.1.  Проверка реентерабельности по  AST  с  помощью
 
                отладчика                                     139
 
      4.4.1.2.  Проверка реентерабельности по AST вручную     139
 
      4.4.2.  Проверка полной реентерабельности               141
 
      4.5.  Анализ производительности                         141
 
      4.5.1.  Входная точка SHOW                              142
 
      4.5.2.  Входная точка STAT                              143
 
      4.6.  Управляющие процедуры исполнительной библиотеки   143
 
 
 
      5.  Oб'единение                                         145
 
      5.1.  Группирование процедур                            145
 
      5.1.1.  Создание префиксов средств                      146


                                - 8 -
 
                           00152-01 97 08
 
 
 
      5.1.2.  Создание библиотек об'ектных модулей            147
 
      5.2.  Разделяемые библиотечные образы                   150
 
      5.2.1.  Создание образов разделяемых библиотек          151
 
      5.2.2.  Создание вектора передачи                       152
 
      5.2.3.  Создание   файла    необязательных    параметров
 
              компоновщика                                    156
 
      5.2.4.  Создание образа разделяемой библиотеки          162
 
      5.2.5.  Об'единение  разделяемых  образов  в  библиотеку
 
              разделяемых образов                             163
 
      5.3.  Компоновка с библиотеками модульных процедур      164
 
 
 
      6.  Сопровождение                                       165
 
      6.1.  Совместимость вперед                              165
 
      6.1.1.  Основные правила                                166
 
      6.1.2.  Регрессионное тестирование                      166
 
      6.1.2.1.  Коррекция вектора передачи                    167
 
      6.2.  Добавление параметров в существующую подпрограмму 168
 
      6.2.1.  Добавление новых параметров в процедуру         169
 
      6.2.2.  Использование блока параметров                  170
 
      6.3.  Корректировка библиотек                           172
 
      6.3.1.  Корректировка об'ектных библиотек               172
 
      6.3.2.  Корректировка разделяемых образов               173
 
      6.3.2.1.  Изменение вектора передачи                    173
 
      6.3.2.2.  Корректировка файла необязательных  параметров
 
                компоновщика                                  174
 
      6.3.3.  Корректировка библиотек разделяемых образов     175
 
 
 
      Приложение 1. Правила модульного программирования       176
 
 
 


                                - 9 -
 
                           00152-01 97 08
 
 
      Приложение 2. Характеристики параметров                 189
 
 
 
 
 
 
 
 
 
      Перечень ссылочных документов                           211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 9K -
     
                          2б.00152-01 97 08
     
     
      Приложение 2. Характеристики параметров                 189
     
     
     
     
     
     
     
     
     
      Перечень ссылочных документов                           211K
     
     
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
            
     
     
     
     
     
     
    

                                - 10 -
 
                           00152-01 97 08
 
 
                  1. Введение в модульные процедуры
 
 
 
           1.1. Жизненный цикл программного обеспечения
 
 
           В данном документе рассматривается разработка  модуль-
 
      ных  процедур,  развитие  библиотек  процедур,  разделяемых
 
      образов и библиотек разделяемых образов в терминах  жизнен-
 
      ного цикла программного обеспечения (ПО).
 
           Существует несколько различных версий понятия  жизнен-
 
      ного цикла ПО. В данном документе жизненный цикл по  описы-
 
      вается как цикл, разбитый на семь этапов:
 
           1) первый этап -  концептуальный,  во  время  которого
 
      предлагается и рассматривается новое предложение по  разра-
 
      ботке;
 
           2) этап требований/спецификаций. На данном этапе выби-
 
      раются  цели  новой  разработки  и  составляется   документ
 
      требований/спецификаций, описывающий в  общих  чертах,  что
 
      должно быть выполнено в результате разработки;
 
           3)  этап  проектирования,  на  котором  детализируются
 
      намеченные планы таким образом,  чтобы  конечная  программа
 
      была бы модульной и точной, так же как и то, чтобы она пол-
 
      ностью   удовлетворяла    целям,    принятым    на    этапе
 
      требований/спецификаций;
 
           4) этап кодирования, во время которого  спроектирован-
 
      ная программа кодируется и документируется (с помощью прог-
 
      раммных комментариев);
 
           5) этап тестирования, на котором закодированная  прог-
 
      рамма проверяется на правильность,  эффективность  и  соот-
 
      ветствие требованиям и спецификациям;
 
           6) этап интеграции, когда процедуры и программы  груп-
 


                                - 11 -
 
                           00152-01 97 08
 
 
      пируются в средства (программные) и библиотеки;
 
           7) этап сопровождения, на котором  завершенная  разра-
 
      ботка корректируется, улучшается и модифицируется.
 
           Модульный принцип становится важным вопросом в жизнен-
 
      ном цикле программы, начиная с фазы проектирования и,  пос-
 
      кольку данный документ главным образом касается  модульнос-
 
      ти, в нем вначале детально обсуждается фаза (этап) проекти-
 
      рования и далее - остальные фазы:  кодирования,  тестирова-
 
      ния, интеграции и сопровождения.
 
 
 
           1.2. Определение модульной процедуры
 
 
           Процедура - это совокупность  соотнесенных  инструкций
 
      (команд), которые  выполняют  определенную  задачу.  Обычно
 
      процедура вызывается  на  выполнение  командами  CALLS  или
 
      CALLG. При использовании языка высокого  уровня  компилятор
 
      генерирует команды CALLS или CALLG при  условии  выполнения
 
      пользователем требуемых для  данного  языка  соглашений  по
 
      обращению к процедурам. Для языков программирования СМ 1700
 
      процедуры определяются следующим образом:
 
           - для языка ADA процедура задается как  процедура  или
 
      функция;
 
           - для языка Бейсик (далее Бейсик) процедурой  является
 
      главная программа, подпрограмма или функция;
 
           - для языка Блисс (далее Блисс) процедура определяется
 
      как подпрограмма;
 
           - в языке  Кобол  (далее  Кобол)  процедурой  является
 
      параграф (или секция) или группа логически последовательных
 
      параграфов в разделе процедур;
 
           - в языке Фортран (далее Фортран) процедурой  является
 


                                - 12 -
 
                           00152-01 97 08
 
 
      главная программа, подпрограмма или функция;
 
           - в Макроассемблере процедура начинается  с  директивы
 
      .ENTRY и оканчивается командой RET;
 
           - для языка Паскаль (далее Паскаль)  процедура  об'яв-
 
      ляется как PROCEDURE или FUNCTION;
 
           - в языке ПЛ/1 (далее ПЛ/1) процедурой является  внеш-
 
      няя или внутренняя процедура или входная точка.
 
           Процедура является модульной, если она следует  прави-
 
      лам и принципам, позволяющим успешно осуществлять связь  ее
 
      с другими процедурами, следующими тем же правилам и принци-
 
      пам. Эти правила  и  принципы  об'единены  в  форме  правил
 
      модульного программирования МОС  ВП,  которые  приведены  в
 
      приложении 1.
 
           Настоящий документ описывает, как решить сложную зада-
 
      чу путем разделения ее  на  модули  и  кодирования  каждого
 
      модуля как отдельную процедуру. Такой подход  к  модульному
 
      программированию обладает рядом преимуществ по сравнению  с
 
      написанием сложной программы в виде одного исходного  моду-
 
      ля:
 
           - имеется  возможность  использовать  любую  модульную
 
      процедуру в любой программе;
 
           - имеется возможность дополнить  библиотеку  модульной
 
      процедурой в любое время;
 
           - нет необходимости переписывать общие алгоритмы  вся-
 
      кий раз, когда в них нуждается новая программа;
 
           - имеется возможность разделить сложную  программу  на
 
      более простые процедуры для сокращения времени  разработки,
 
      упрощения сопровождения и повышения надежности;
 
           - есть возможность заменить процедуру, не  прибегая  к
 
      модификации вызывающей программы,  что  обеспечивается  при


                                - 13 -
 
                           00152-01 97 08
 
 
      соблюдении пользователем необязательных рекомендаций правил
 
      модульного программирования;
 
           - имеется возможность управлять распределением  ресур-
 
      сов в диапазоне процесса;
 
           - есть возможность применять различные языки  програм-
 
      мирования для написания различных процедур для программы.
 
           Правила  модульного  программирования  содержат  также
 
      необязательные  рекомендации.  Следуя  этим  рекомендациям,
 
      пользователь получает дополнительные преимущества:
 
           - разделяемые библиотечные процедуры экономят  память,
 
      дисковое пространство и время компоновки;
 
           - повторно-используемые  (реентерабельные)   процедуры
 
      уровня асинхронного системного прерывания могут  вызываться
 
      процедурами  уровня  асинхронного   системного   прерывания
 
      (AST);
 
           - модульные процедуры, которые отвечают всем  рекомен-
 
      дациям по кодированию, аналогичны по формату, и поэтому  их
 
      легче использовать и обслуживать.
 
           Модульные процедуры можно использовать при общем прог-
 
      раммировании или группировать в библиотеки  процедур.  Биб-
 
      лиотеки являются лишь  способом  об'единения  процедур  для
 
      простоты доступа к ним со стороны вызывающих программ.  При
 
      компоновке программы с библиотекой компоновщик автоматичес-
 
      ки просматривает библиотеку и разрешает обращения,  которые
 
      программа пользователя делает к процедурам библиотеки.  Так
 
      как компоновщик просматривает указанную библиотеку  автома-
 
      тически, программа пользователя  может  вызывать  несколько
 
      модульных процедур без указания каждой из них явно в коман-
 
      де LINK. Выполняемый образ программы  и  вызываемые  в  нем
 
      процедуры выполняются в требуемой последовательности.


                                - 14 -
 
                           00152-01 97 08
 
 
           На рис. 1 показан процесс подготовки программы,  кото-
 
      рая вызывает процедуры из библиотеки:
 
           - этап  1  -  редактирования.  Осуществляется  ввод  и
 
      редактирование программы;
 
           - этап 2 - компиляции. Компилятор транслирует отредак-
 
      тированную программу в об'ектный файл;
 
           - этап 3 - компоновки. Компоновщик обследует (просмат-
 
      ривает) библиотеку об'ектных модулей и разделяемые  образы.
 
      Необходимые входные точки  библиотеки  становятся  известны
 
      об'ектному  модулю  пользователя,  после  чего  формируется
 
      выполняемый образ;
 
           - этап 4  -  выполнения.  Выполняемому  образу  теперь
 
      известны адреса необходимых библиотечных процедур  в  своем
 
      пространстве виртуальных адресов. Образ может  вызывать  во
 
      время выполнения библиотечные процедуры.
 
           В зависимости от варианта написания модульных процедур
 
      пользователь может управлять доступом компоновщика к проце-
 
      дурам и, следовательно, способом отработки процедур. Напри-
 
      мер, размещение совместно используемых процедур в разделяе-
 
      мом образе или в библиотеке  разделяемых  образов  экономит
 
      память и пространство  на  диске,  поскольку  все  процессы
 
      пользователя обращаются к одной копии процедуры.
 
 
 
           1.3. Процедуры системы МОС ВП
 
 
           Операционная система МОС  ВП  содержит  большой  набор
 
      системных программ, которые удовлетворяют потребности поль-
 
      зователей для успешного и всестороннего применения. Поэтому
 
      до написания новой процедуры необходимо убедиться, что
 
 
 


                                - 15 -
 
                           00152-01 97 08
 
 
               Ппроцесс подготовки программ к выполнению
 
                                   интерактивный ввод
                                           !
                                           V
             --  ------------------  -----------------
             !   !исходные модули !<-!  редактор     !
      Этап1  !   !                !  -----------------
             !   ! имя_файла.XXX  !----------
             --  ------------------         !
                          !                 !
                          V                 V
             --  ------------------  -----------------
             !   !об'ектные модули!  !  компилятор   !
      Этап2  !   !                !<-!               !
             !   ! имя_файла.OBJ  !  !     или       !
             !   ------------------  !               !
             !           !   !       !  ассемблер    !
             --          !   !       -----------------
                         !   !             !
                         !   !             V
                         !   !      -----------------
                         !   !      ! имя_файла.LIS !  ----------
                         !   !      -----------------  !разделя-!
             --          !   !                         !        !
             !           !   !      -----------------  !емый об-!
             !           !   !----->! компоновщик   !<-!        !
             !           V          -----------------  !  раз   !
             !  -------------------      !  !  а       ----------
             !  !выполняемый образ!      !  !  !       ----------
      Этап3  !  !                 !<-----!  !  !-------!библио- !
             !  !  имя_файла.EXE  !         V          !        !
             -- ------------------- -----------------  !теки    !
                         !          ! имя_файла.MAP !  !        !
            --           !          -----------------  !об'ект- !
            ! выполнение ! имя_файла.EXE               !        !
            !            V                             !ных мо- !
            !    -------------------------             !        !
            !    !  -------------------  !             !дулей   !
            !    !  !   разделяемый   !  !             ----------
            !    !  !                 !  !
            !    !  !     образ       !  !
            !    !  -------------------  !   --------------------
            !    !  -------------------  !   !    выходная      !
      Этап4 !    !  !   вызываемые    !  !-->!                  !
            !    !  !                 !  !   !   информация     !
            !    !  !об'ектные модули !  !   !                  !
            !    !  -------------------  !   !    программы     !
            !    !                       !   --------------------
            !    !выполняемый(е) образ(ы)!
            --   -------------------------
 
                                Рис. 1
 
 
 
 
 
 


                                - 16 -
 
                           00152-01 97 08
 
 
      подобной еще не существует.
 
           Можно так же обнаружить, что системные процедуры имеют
 
      встроенные блоки, полезные для  программы  пользователя.  В
 
      системных библиотеках уже существуют процедуры,  предназна-
 
      ченные для выполнения разнообразных  функций,  и  процедура
 
      пользователя может просто вызвать существующую процедуру, а
 
      не дублировать нужную функцию.
 
           Перечень четырех подсистем,  чьи  системные  процедуры
 
      можно вызывать:
 
           1) исполнительная библиотека МОС ВП [1];
 
           2) системный сервис [2];
 
           3) обслуживающие программы [3];
 
           4) система управления данными (СУД) [4].
 
 
 
           1.3.1. Процедуры исполнительной библиотеки
 
 
           Общая исполнительная библиотека проседур  системы  мос
 
      вп (или просто исполнительная библиотека) содержит процеду-
 
      ры двух видов:
 
           1) процедуры общего назначения;
 
           2) процедуры поддержки языков программирования.
 
           Исполнительная библиотека обеспечивает общую  исполни-
 
      тельную среду для программ пользователя, поскольку процеду-
 
      ры этой библиотеки соответствуют правилам модульного  прог-
 
      раммирования в системе МОС ВП. Краткий обзор процедур, дос-
 
      тупных в исполнительной библиотеке, дает рис. 2.
 
 
 
 
 
 
 
 
 


                                - 17 -
 
                           00152-01 97 08
 
 
                 Процедуры исполнительной библиотеки
 
 
                 Процедуры общего назначения
 
      ------------ ---------- ---------- ---------- -----------
      !Математи-  !Процедуры !Процедуры !Процедуры !Процедуры !
      !           !          !          !          !          !
      !ческие про-!обслужива-!распреде- !сигнализа-!специаль- !
      !           !          !          !          !          !
      !цедуры     !ния экрана!ления ре- !ции и об- !ного при- !
      !           !          !          !          !          !
      !           !          !сурсов в  !работки   !менения   !
      !           !          !          !          !          !
      !           !          !рамках    !условий   !          !
      !           !          !          !          !          !
      !           !          !процесса  !          !          !
      !           !          !          !          !          !
      ! MTH$      ! SMG$     ! LIB$     ! LIB$     ! LIB$     !
      !           !          !          !          !          !
      ! OTS$      !          ! STR$     !          !          !
      !           !          !          !          !          !
      !           !          ! OTS$     !          !          !
      ---------------------------------------------------------
 
               Процедуры поддержки языков программирования
 
         -----------------------     -------------------------
         ! Процедуры поддержки,!     ! Процедуры поддержки   !
         !                     !     !                       !
         ! независящие от      !     ! конкретных языков     !
         !                     !     !                       !
         ! языка программирова-!     ! программирования:     !
         !                     !     !                       !
         ! ния                 !     !  -поддержка скомпили- !
         !                     !     !                       !
         !                     !     ! рованной программы;   !
         !                     !     !                       !
         ! (применимы для      !     !  -обработка файлов;   !
         !                     !     !                       !
         ! более чем одного    !     !  -обработка форматов; !
         !                     !     !                       !
         ! языка программиро-  !     !  -обработка ошибок;   !
         !                     !     !                       !
         ! вания)              !     !  -обработка ввода-вы- !
         !                     !     !                       !
         !                     !     ! вода                  !
         !                     !     !                       !
         !                     !     !    ADA$    PAS$       !
         !                     !     !                       !
         !                     !     !    BAS$    PLI$       !
         !                     !     !                       !
         !                     !     !    COB$    RPG$       !
         !                     !     !                       !
         !                     !     !    FOR$               !
         -----------------------     -------------------------
 
                                Рис. 2
 


                                - 18 -
 
                           00152-01 97 08
 
 
           Процедуры исполнительной  библиотеки  наиболее  общего
 
      назначения  являются  реентерабельными  (подраздел  3.3)  и
 
      позиционно независимыми (п. 3.1.1). Процедуры  исполнитель-
 
      ной библиотеки могут использоваться в сочетании со  средст-
 
      вами системного обслуживания. Преимущество  общей  исполни-
 
      тельной среды заключается в том, что любая программа, напи-
 
      санная на Макроассемблере, БЛИССЕ или языке высокого  уров-
 
      ня, может обращаться к любой  процедуре  из  исполнительной
 
      библиотеки.
 
           Табл. 1 описывает процедуры исполнительной  библиотеки
 
      МОС ВП.
 
                                                        Таблица 1
 
                  Процедуры исполнительной библиотеки
 
      -----------------------------------------------------------
                         !
          Процедуры      !     Назначение
                         !
      -----------------------------------------------------------
                         !
      Общие обслуживающие!   Данная группа содержит процедуры для
                         !
                         !считывания записи с устройства, выпол-
                         !
                         !нения преобразований со строкой симво-
                         !
                         !лов, преобразования типов данных при
                         !
                         !вводе и выводе и получения информации
                         !
                         !о дате и системном времени
                         !
      Математические     !   Математические процедуры выполняют
                         !
                         !общие арифметические, алгебраические и
                         !
                         !тригонометрические операции, такие,
                         !
                         !например, как вычисление синуса угла
                         !
      Распределение      !   Процедуры распределения ресурсов
                         !
      ресурсов           !выделяют или освобождают виртуальную
                         !
                         !память, номера флагов локальных собы-
                         !
                         !тий, номера логических устройств в бэй-


                                - 19 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 1
      -----------------------------------------------------------
                         !
          Процедуры      !     Назначение
                         !
      -----------------------------------------------------------
                         !
                         !сике, Фортране и динамические строки
                         !
      Обслуживание экрана!   Процедуры обслуживания экрана
                         !
                         !выполняют операции по обслуживанию
                         !
                         !экрана, не зависящие от типа терминала
                         !
                         !такие процедуры помогают при разработ-
                         !
                         !ке, составлении и слежении за сложными
                         !
                         !изображениями на экране видеотерминала
                         !
      Сигнализация и     !   Эти процедуры выполняют операции,
                         !
      обработка условий  !связанные с обработкой исключительных
                         !
                         !ситуаций, таких как сигнализация об
                         !
                         !исключительной ситуации, установка
                         !
                         !программ обработки условий и разрешение
                         !
                         !распознавания аппаратных прерываний
                         !
      Языковонезависимая !   Процедуры поддержки, не зависящие от
                         !
      поддержка          !языка программирования, могут вызывать-
                         !
                         !ся из программы, написанной на любом из
                         !
                         !имеющихся в системе МОС ВП языке
                         !
                         !программирования. Хотя большинство та-
                         !
                         !ких подпрограмм находится в разделе
                         !
                         !OTS$, некоторые подпрограммы раздела
                         !
                         !LIB$ также выполняют операции, связан-
                         !
                         !ные с языком программирования. В боль-
                         !
                         !шинстве своем процедуры поддержки, не
                         !
                         !зависящие от языка программирования,
                         !
                         !это процедуры преобразования типов
                         !
                         !данных
                         !


                                - 20 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 1
      -----------------------------------------------------------
                         !
          Процедуры      !     Назначение
                         !
      -----------------------------------------------------------
      Специального       !   Процедуры для специального примене-
                         !
      применения         !ния, такого как синтаксический анализ
                         !
                         !и перекрестные ссылки, также имеются в
                         !
                         !исполнительной библиотеке МОС ВП
                         !
 
 
           1.3.2. Программы системного обслуживания
 
 
           Средства  системного  обслуживания  -  это  процедуры,
 
      которые используются операционной системой  для  управления
 
      ресурсами, доступными процессам. Они также используются для
 
      обеспечения связи между процессами и для выполнения  основ-
 
      ных функций операционной  системы,  таких  как  координация
 
      операций ввода-вывода.
 
           Хотя  большинство  операций  системного   обслуживания
 
      выполняются в первую очередь  самой  операционной  системой
 
      для зарегистрированных пользователей, многие из них доступ-
 
      ны для применения в прикладных  программах.  Например,  при
 
      входе в систему вызывается программа системного  обслужива-
 
      ния "создать процесс" ($CREPRC) для создания процесса поль-
 
      зователя. Можно написать программу, которая будет,  в  свою
 
      очередь, обращаться к $CREPRC для создания подпроцесса.
 
           Средства  системного  обслуживания  можно  разбить  на
 
      функциональные группы. В табл. 2  перечисляется  назначение
 
      каждой из групп средств системного обслуживания.
 


                                - 21 -
 
                           00152-01 97 08
 
 
                                                        Таблица 2
 
                  Программы средств системного обслуживания
 
      -----------------------------------------------------------
                            !
      Группа средств сис-   !
                            !          Назначение
      темного обслуживания  !
                            !
      -----------------------------------------------------------
                            !
      Защита                !  Средствами защиты обеспечиваются
                            !
                            !различные механизмы, которыми можно
                            !
                            !пользоваться для повышения
                            !
                            !защищенности подсистем МОС ВП
                            !
      Флаг событий          !  Флаги событий могут использоваться
                            !
                            !процессом для синхронизации в прог-
                            !
                            !рамме последовательности операций
                            !
                            !средства обслуживания флага события
                            !
                            !сбрасывают, устанавливают и считыва-
                            !
                            !ют флаги событий, переводят процесс
                            !
                            !в состояние ожидания установки
                            !
                            !флага или флагов событий
                            !
      Асинхронное системное !  Выполнение процесса может быть
                            !
      прерывание (AST)      !прервано событиями (например, завер-
                            !
                            !шением операции ввода-вывода), чтобы
                            !
                            !смогли выполниться определенные под-
                            !
                            !программы. Такие программные преры-
                            !
                            !вания называются асинхронными сис-
                            !
                            !темными прерываниями (AST), посколь-
                            !
                            !ку они возникают асинхронно по отно-
                            !
                            !шению к выполняющемуся процессу.
                            !
                            !существуют такие средства системного
                            !
                            !обслуживания, которые позволяют
                            !
                            !процессу управлять обработкой AST


                                - 22 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 2
      -----------------------------------------------------------
                            !
      Группа средств сис-   !
                            !          Назначение
      темного обслуживания  !
                            !
      -----------------------------------------------------------
                            !
      Логические имена      !  Средства обслуживания логических
                            !
                            !имен используются для работы и дос-
                            !
                            !тупа к парам "строка символов - эк-
                            !
                            !вивалентное имя (логическое имя)".
                            !
                            !логическими именами можно обеспе-
                            !
                            !чить независимость операций
                            !
                            !ввода и вывода системных и
                            !
                            !прикладных программ от устройства
                            !
      Ввод-вывод            !  Средства обслуживания ввода-вывода
                            !
                            !выполняют операции ввода-вывода на-
                            !
                            !прямую, а не через средства
                            !
                            !обслуживания файлов системы управ-
                            !
                            !ления данными системы МОС ВП
                            !
                            !(СУД-32). Средства обслуживания
                            !
                            !ввода-вывода делают следующее:
                            !
                            !  - выполняют операции логического,
                            !
                            !физического и виртуального
                            !
                            !ввода-вывода;
                            !
                            !  - выполняют операции сетевого об-
                            !
                            !мена;
                            !
                            !  - организуют очереди сообщений,
                            !
                            !адресованных системным процессам
                            !
      Управление процессом  !  Средства управления процессом поз-
                            !
                            !воляют создавать, уничтожать про-
                            !
                            !цессы и управлять их выполнением
                            !


                                - 23 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 2
      -----------------------------------------------------------
                            !
      Группа средств сис-   !
                            !          Назначение
      темного обслуживания  !
                            !
      -----------------------------------------------------------
      Таймер и преобразова- !  Средства обслуживания таймера
                            !
      ние времени           !планируют события в программе в
                            !
                            !связи с конкретным временем дня или
                            !
                            !по истечении заданного интервала
                            !
                            !(промежутка) времени. Средства
                            !
                            !обслуживания преобразования времени
                            !
                            !предоставляют способ получения
                            !
                            !и форматирования двоичных отсчетов
                            !
                            !времени, которые используются
                            !
                            !средствами обслуживания таймера
                            !
      Обработка условий     !  Программы обработки условий - это
                            !
                            !процедуры, которым передается
                            !
                            !управление, если в ходе выполнения
                            !
                            !образа встречается программное или
                            !
                            !аппаратное условие исключительной
                            !
                            !ситуации. Средства обслуживания
                            !
                            !обработки условий представляют
                            !
                            !собой программы обработки условий
                            !
                            !специального назначения
                            !
      Управление памятью    !  Средства обслуживания управлением
                            !
                            !памятью предоставляют различные
                            !
                            !способы использования виртуального
                            !
                            !адресного пространства, доступного
                            !
                            !программе. К этой группе относятся
                            !
                            !средства обслуживания, которые
                            !
                            !выполняют следующие операции:


                                - 24 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 2
      -----------------------------------------------------------
                            !
      Группа средств сис-   !
                            !          Назначение
      темного обслуживания  !
                            !
      -----------------------------------------------------------
                            !
                            !  - разрешают образу увеличивать
                            !
                            !или уменьшать об'ем доступной вир-
                            !
                            !туальной памяти;
                            !
                            !  - управляют разбиением на страни-
                            !
                            !цы и обменом рабочих наборов
                            !
                            !виртуальной памяти;
                            !
                            !  - создают и осуществляют доступ
                            !
                            !к файлам, находящимся в памяти и
                            !
                            !содержащим разделяемые программу
                            !
                            !или данные
                            !
      Смена режима          !  Средства обслуживания смены режима
                            !
                            !изменяют для процесса режим досту-
                            !
                            !па. Такие средства обслуживания
                            !
                            !в основном используются операцион-
                            !
                            !ной системой
                            !
      Обслуживание          !  Средства обслуживания блокировок
                            !
      блокировок            !позволяют взаимодействующим процес-
                            !
                            !сам синхронизировать свой доступ к
                            !
                            !разделяемым ресурсам
 


                                - 25 -
 
                           00152-01 97 08
 
 
           1.3.3. Обслуживающие программы
 
 
           Обслуживающие программы  выполняют  конкретную  задачу
 
      или набор задач. Например, подпрограммы изменения симбионта
 
      вывода на печать (PSM) можно использовать  для  модификации
 
      симбионта вывода на печать системы МОС ВП,  а  подпрограммы
 
      EDT могут использоваться для вызова редактора EDT из  прог-
 
      раммы.
 
           Если используется ряд обслуживающих программ,  которые
 
      выполняют те же задачи, что и обслуживающая программа  сис-
 
      темы МОС ВП, следует ознакомиться с документацией по  соот-
 
      ветствующей обслуживающей программе МОС ВП.  Так  же  можно
 
      извлечь дополнительную информацию о задачах, которые  можно
 
      выполнить с помощью каждой подпрограммы. В табл. 3 перечис-
 
      лены обслуживающие программы системы МОС ВП.
 
                                                        Таблица 3
 
                   Системные обслуживающие программы
 
      -----------------------------------------------------------
                       !
      Группа программ  !       Назначение
                       !
      -----------------------------------------------------------
                       !
      Интерпретатор    !  Подпрограммы интерпретатора команд
                       !
      команд (CLI)     !обрабатывают строки команд, используя
                       !
                       !информацию из таблицы команд. Таблица
                       !
                       !команд - это перечень определений,
                       !
                       !которые описывают допустимые форматы
                       !
                       !команд
                       !
      Преобразование и !  Программы CONV копируют записи из
                       !
      копирование      !одного или нескольких файлов в выходной
                       !
      файлов (CONV)    !файл, изменяя формат записи и организацию
                       !
                       !файла в соответствии с характеристиками
                       !


                                - 26 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 3
      -----------------------------------------------------------
                       !
      Группа программ  !       Назначение
                       !
      -----------------------------------------------------------
                       !выходного файла. Эти программы исправляют
                       !
                       !пустые бакеты индексных файлов "пролог 3"
                       !
                       !таким образом, чтобы в них можно было
                       !
                       !занести новые записи. Эти подпрограммы
                       !
                       !нельзя вызывать на уровне обработки
                       !
                       !асинхронных системных прерываний
                       !
      Язык описания    !  Подпрограммы языка описания файлов
                       !
      файлов (FDL)     !выполняют многие операции языка описания
                       !
                       !файлов СУД-32. Эти подпрограммы нельзя
                       !
                       !вызывать на уровне обработки асинхронных
                       !
                       !системных прерываний
                       !
      Библиотекарь     !  Подпрограммы библиотекаря используются
                       !
      (LBR)            !для создания и обслуживания библиотек
                       !
                       !и библиотечных модулей. Библиотеки - это
                       !
                       !файлы, которые обеспечивают удобный
                       !
                       !способ организации часто используемых
                       !
                       !программных или текстовых модулей
                       !
      Сортировка/сли-  !  Программы SOR используются для
                       !
      яние (SOR)       !операций сортировки или слияния внутри
                       !
                       !программы. Эти программы являются
                       !
                       !реентерабельными, то есть одновременно
                       !
                       !может выполняться некоторое число
                       !
                       !операций сортировки либо слияния
 
           Средства, указанные в табл.4, доступны только на уров-
 
      не подпрограмм обслуживания.
 


                                - 27 -
 
                           00152-01 97 08
 
 
                                                        Таблица 4
 
                        Обслуживающие программы
 
      -----------------------------------------------------------
                         !
      Группа программ    !      Назначение
                         !
      -----------------------------------------------------------
                         !
      Сжатие/расширение  !  Программы группы DCX используются
                         !
      данных (DCX)       !для анализа и сжатия записей данных и
                         !
                         !последующего расширения сжатых записей
                         !
                         !до их исходного состояния. В ходе
                         !
                         !таких операций сжатия/расширения
                         !
                         !нет потери информации
                         !
      Редактор (EDT)     !  Программа EDT вызывает редактор
                         !
                         !EDT изнутри программы. Программа
                         !
                         !может быть написана для обработки
                         !
                         !результатов редактирования. Можно
                         !
                         !так же запустить EDT в интерактивном
                         !
                         !режиме, что позволит пользователю
                         !
                         !за терминалом редактировать некоторый
                         !
                         !файл во время прогона программы
                         !
      Симбионт вывода на !  Программы группы PSM изменяют поведе-
                         !
      печать (PSM)       !ние симбионта вывода на печать, который
                         !
                         !поставляется в рамках операционной
                         !
                         !системы МОС ВП
                         !
      Интерфейс симбионта!  Программы группы SMB обеспечивают
                         !
      /котроллера задания!интерфейс между процессами контроллера
                         !
      (SMB)              !задания и симбионта


                                - 28 -
 
                           00152-01 97 08
 
 
           1.3.4. Система управления данными СУД-32
 
 
           СУД-32 оказывает  помощь  программам  пользователей  в
 
      обработке и обслуживании файлов и  их  содержимого.  СУД-32
 
      позволяет создавать файлы, которые  используют  минимальные
 
      системные ресурсы, снижая одновременно затраты  времени  на
 
      ввод-вывод. Существует два вида системы управления данными,
 
      краткое описание которых содержится в табл. 5 [4].
 
                                                        Таблица 5
 
                    Система управления данными
 
      -----------------------------------------------------------
                               !
      Группа средств СУД-32    !         Назначение
                               !
      -----------------------------------------------------------
                               !
      Средства, ориентированные!  Средства, ориентированные на
                               !
      на работу с файлами      !работу с файлами, создают и
                               !
                               !организуют доступ к новым файлам,
                               !
                               !осуществляют доступ к существую-
                               !
                               !щим файлам, расширяют пространст-
                               !
                               !во на диске, выделенное для фай-
                               !
                               !ла, закрывают файл, считывают
                               !
                               !характеристики файла и выполняют
                               !
                               !прочие операции, которые связаны
                               !
                               !с файлом как с неделимым об'ек-
                               !
                               !том
                               !
      Средства, ориентированные!  Средства, ориентированные на
                               !
      на работу с записями     !работу с записями, считывают,
                               !
                               !отыскивают местонахождение,
                               !
                               !вставляют, удаляют и обновляют
                               !
                               !информацию записей, а также
                               !
                               !выполняют прочие, связанные с
                               !


                                - 29 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 5
      -----------------------------------------------------------
                               !
      Группа средств СУД-32    !         Назначение
                               !
      -----------------------------------------------------------
                               !обслуживанием записей, операции
 
 
 
           1.4. Средства  разработки   прикладного   программного
 
      обеспечения в МОС ВП
 
 
           В целях облегчения разработки  прикладных  программ  в
 
      МОС ВП существует ряд средств:
 
           1) система сопровождения программ (CMS) - система биб-
 
      лиотек программ для разработки и сопровождения программного
 
      обеспечения. Система сопровождения программ выполняет функ-
 
      ции библиотекаря, работающего в темпе с  реализацией  прог-
 
      раммного проекта. Пока участники проекта выполняют  обычные
 
      операции по разработке, изменению и  тестированию  программ
 
      проекта, система сопровождения программ сохраняет запись  о
 
      тех изменениях, которые претерпели файлы проекта;
 
           2) система управления модулями (MMS) - средство, кото-
 
      рое автоматизирует и упрощает построение  программных  сис-
 
      тем. MMS полезна как при построении простых программ, кото-
 
      рые могут иметь всего один или два исходных  файла,  так  и
 
      при построении сложных программ,  которые  могут  образовы-
 
      ваться из ряда файлов исходных текстов, файлов сообщений  и
 
      документации. С помощью системы управления  модулями  можно
 
      перестроить все компоненты системы, либо только те их  них,
 
      которые претерпели изменения с момента  последней  редакции
 
      системы;
 
           3) система управления тестированием - средство,  кото-
 
      рым организуются проверки программного обеспечения и  авто-
 


                                - 30 -
 
                           00152-01 97 08
 
 
      матизируются способы прогона тестов, а также оценки резуль-
 
      татов. Этим  средством  обеспечивается  эффективный  способ
 
      организации, прогона и сбора результатов завершающихся тес-
 
      тов. Средство управления тестированием основывается на кон-
 
      цепции регрессионного тестирования;
 
           4) языково-ориентированный редактор - редактор  исход-
 
      ных текстов программ, который позволяет быстро и  правильно
 
      разрабатывать программы с помощью команд EDT. Данный редак-
 
      тор имеет полезные средства разработки программ, такие  как
 
      готовые шаблоны и трафареты, шаблоны и  трафареты,  опреде-
 
      ленные пользователем, а также команды. Среди прочих возмож-
 
      ностей имеются интерфейс с компилятором и подсказки по язы-
 
      ку программирования в режиме "ON LINE";
 
           5) анализатор обзорной информации о выполнении и  тес-
 
      тировании (PCA) - средство, которым  могут  воспользоваться
 
      разработчики программного обеспечения  для  сбора  обзорных
 
      данных о выполнении или тестировании пользовательских прог-
 
      рамм. Затем эти данные могут быть представлены в виде  таб-
 
      лиц,  линейных  гистограмм,   комментированных   распечаток
 
      исходных текстов и в иных формах.
 
           Описанные средства являются необязательными  программ-
 
      ными продуктами. Они не входят в комплект поставки  системы
 
      МОС ВП. Дальнейшую информацию по этим программным продуктам
 
      можно получить у организаций - поставщиков.
 
 
 
 
 
 


                                - 31 -
 
                           00152-01 97 08
 
 
                          2. Проектирование
 
 
 
           Удачно спроектированные процедуры, по всей  видимости,
 
      должны быть модульными, хорошо  написанными  и  удобными  в
 
      сопровождении. Все сэкономленное  на  этапе  проектирования
 
      время оборачивается многократными потерями, выражающимися в
 
      попытках внесения исправлений для устранения  тех  проблем,
 
      которые являются следствием неудачного проектирования.
 
           Данный раздел поможет пользователю в следующих  аспек-
 
      тах разработки новых прикладных программ:
 
           - организация новых прикладных программ;
 
           - разработка интерфейса модульной процедуры;
 
           - использование системных ресурсов;
 
           - использование ввода-вывода;
 
           - самодокументирование;
 
           - планирование обработки сигналов и условий.
 
 
 
           2.1. Организация разрабатываемых прикладных программ
 
 
           При разработке новой  прикладной  программы  в  первую
 
      очередь необходимо просмотреть ее общую организацию.  Прик-
 
      ладная программа будет формироваться из одного или несколь-
 
      ких файлов, каждый из которых будет содержать одну или нес-
 
      колько процедур. При компоновке процедуры будут оформлены в
 
      виде программных секций (PSECT). Каждую процедуру, а  также
 
      интерфейс между процедурами следует разрабатывать  в  соот-
 
      ветствии правилами модульного  программирования  в  системе
 
      МОС ВП (см. Приложение 1).
 


                                - 32 -
 
                           00152-01 97 08
 
 
           2.1.1. Организация файлов и модулей
 
 
           В прикладной программе может использоваться  один  или
 
      несколько файлов. Каждый файл должен содержать  точно  один
 
      модуль (подпункты 3.1.2.3, 3.1.2.4).
 
 
 
           2.1.2. Организация процедур внутри модулей
 
 
           Каждый модуль должен  содержать  одну  процедуру  либо
 
      группу взаимосвязанных процедур. Компоновщик системы МОС ВП
 
      всегда помещает целиком модуль, содержащий вызываемую  про-
 
      цедуру, в образ, если имеется ссылка хотя бы на одну из его
 
      точек входа. Следовательно, помещение процедуры в отдельный
 
      модуль экономит размер образа.  Этим  также  обеспечивается
 
      большая гибкость  для  использования  библиотеки  процедур,
 
      поскольку можно заменить одну из своих процедур на процеду-
 
      ры из библиотеки. Если несколько процедур были сгруппирова-
 
      ны в один модуль,  компоновщик  должен  отредактировать  их
 
      связи полностью (для всех процедур) либо не должен их вооб-
 
      ще использовать.
 
           Группировать процедуры в модуль следует только  в  том
 
      случае, когда они совместно используют одну и ту же область
 
      статической памяти либо обладают  аналогичными  вызывающими
 
      последовательностями, выполняют аналогичные операции и сов-
 
      местно используют значительный об'ем машинных команд  прог-
 
      раммы.
 
           Если пишется большое число  взаимосвязанных  процедур,
 
      которые обращаются одна к другой либо осуществляют доступ к
 
      общим блокам данных, следует взаимосвязь между такими  про-
 
      цедурами сделать как можно более ясной. Сделать  это  можно
 
      за счет такой организации процедур, при  которой  минимизи-


                                - 33 -
 
                           00152-01 97 08
 
 
      руется взаимодействие между процедурами и между процедурами
 
      и структурами данных. Имеется несколько  основных  приемов,
 
      которые могут помочь минимизировать такое взаимодействие:
 
           - организация процедур по уровням абстрагирования;
 
           - обеспечение того, чтобы вызовы каждого уровня  отно-
 
      сились только к следующему более низкому уровню;
 
           - сведение до минимума  количества  процедур,  имеющих
 
      доступ к структурам данных и системным компонентам для чте-
 
      ния-записи.
 
           Рис. 3 иллюстрирует процедуры обработки обмена запися-
 
      ми языков Бейсик и Фортран. Они реализованы в виде  следую-
 
      щих трех уровней абстракции:
 
           1) интерфейс программы пользователя (UPI);
 
           2) форматирование данных программы пользователя (UDF);
 
           3) обработка записей и интерфейс СУД-32 (REC).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 34 -
 
                           00152-01 97 08
 
 
                     Уровни абстракции
 
                -----------  -----------  -----------
                !         !  !         !  !         !  Уровень C:
                !Процедура!  !Процедура!  !Процедура!
                !         !  !         !  !         !  интерфейс
                ! типа C  !  ! типа C  !  ! типа C  !
                !         !  !         !  !         !   СУД-32
                -----------  -----------  -----------
                        а             а      а
                        !             !      !
                        !   ------------------
        А               !   !         !
        !             -----------  -----------
      Направле-       !         !  !         !    Уровень B:
                      !Процедура!  !Процедура!
      ние всех        !         !  !         !    форматирование
                      !  типа B !  !  типа B !
       вызовов        !         !  !         !    данных програм-
        А             -----------  -----------
        !               а            а а   а      мы пользователя
                        ! -----------! !   !
                        ! !            !   !
                -----------  -----------  -----------
                !         !  !         !  !         ! Уровень A:
                !Процедура!  !Процедура!  !Процедура!
                !         !  !         !  !         ! интерфейс
                ! типа A  !  ! типа A  !  ! типа A  !
                !         !  !         !  !         ! программы
                -----------  -----------  -----------
                        а            а           а   пользователя
                        !            !           !
                        !            !           !
             ------------------------------------------ Модульный
                        !            !           !
                        !            !           !      интерфейс
                  -------------------------------------
                  !                                   !
                  !       Основная программа          !
 
                                Рис. 3
 
 
           Все вызовы выполняются в одном направлении, с верхнего
 
      на следующий наиболее внутренний уровень. Процедуры различ-
 
      ных уровней должны находиться в различных модулях. Рис. 4-6
 
      иллюстрируют возможные варианты группировки процедур.
 
 
 
 
 
 
 
 
 


                                - 35 -
 
                           00152-01 97 08
 
 
                !  Модуль
 
                ! -----------------------------------------
                  !                                       !
                ! !  ----------------                     !
                ! !  !              !                     !
                  !  ! Статическая  !                     !
                ! !  !              !                     !
                  !  ! память       !<-----------         !
                ! !  !              !           !         !
                  !  !(произвольная)!           !         !
                ! !  !              !           !         !
                ! !  ----------------           !         !
                  !       A                     !         !
                ! !       ! Чтение-             !         !
                  !       !                     !         !
                ! !       ! запись              !         !
                  !       !                     !         !
                ! !       V                     !         !
      --------- ! ! ----------------            !         !
      !       !   ! !              !            !         !
      !Вызов--!---->! Модульная    !            !         !
      !       !   ! !              !            !         !
      !       ! ! ! ! процедура    !            !         !
      !       !   ! !              !            !         !
      !     <-!---!-! RET (возврат)!            !         !
      !       ! ! ! !              !            !         !
      !       !   ! ----------------            V         !
      !       ! ! !                   ------------------- !
      !       !   !                   !                 ! !
      !Вызов--!---!------------------>!   Модульная     ! !
      !       ! ! !                   !                 ! !
      !       !   !                   !   процедура     ! !
      !       ! ! !                   !                 ! !
      !       ! ! !                   !(необязательная) ! !
      !       !   !                   !                 ! !
      !     <-!---!-------------------! RET (возврат)   ! !
      !       !   !                   !                 ! !
      !       ! ! !                   ------------------- !
      !       !   !                                       !
      --------- ! -----------------------------------------
                !
            Интерфейс
 
                                Рис. 4
 
 
 


                                - 36 -
 
                           00152-01 97 08
 
 
                !                     !
      ---------          Модуль
      !       ! !                     !
      !       !   --------------------  -------------------
      !       ! ! !                  !! !                 !
      !       ! ! ! ---------------- !! !---------------- !
      !       !   ! !              ! !  !!              ! !
      !       ! ! ! ! Статическая  ! !! !! Статическая  ! !
      !       !   ! !              ! !  !!              ! !
      !       ! ! ! !  память      ! !! !!  память      ! !
      !       !   ! !              ! !  !!              ! !
      !       ! ! ! !(произвольная)! !! !!(произвольная)! !
      !       ! ! ! !              ! !! !!              ! !
      !       !   ! ---------------- !  !! RET          ! !
      !       ! ! !      A           !! !---------------- !
      !       !   !      ! Чтение-   !  !     A           !
      !       ! ! !      !           !! !     ! Чтение-   !
      !       !   !      ! запись    !  !     !           !
      !       ! ! !      V           !! !     ! запись    !
      !       ! ! ! ---------------- !! !     V           !
      !       !   ! !              ! !  !---------------- !
      !       ! ! ! ! Модульная    ! !! !!              ! !
      !Вызов--!---->!              !---->!         CALL ! !
      !       ! ! ! ! процедура    ! !! !!              ! !
      !       !   ! !              ! !  !! Модульная    ! !
      !     <-!---!-! RET          !<-! !!              ! !
      !       ! ! ! ---------------- !! !! процедура    ! !
      !       ! ! !                  !  !!              ! !
      !       !   !                  !---! RET          ! !
      --------- ! --------------------  !---------------- !
                !                     ! -------------------
                !                     !
                !                     !
                !                     !
                !                     !
                !                     !
            Интерфейс            Интерфейс
 
 
 
 
                                Рис. 5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 37 -
 
                           00152-01 97 08
 
 
                                 Модуль
 
      --------- ! ---------------------------------------------
      !       ! ! !                                           !
      !       !   ! ----------------                          !
      !       ! ! ! !              !                          !
      !       !   ! ! Статическая  !                          !
      !       ! ! ! !              !                          !
      !       !   ! !  память      !                          !
      !       ! ! ! !              !                          !
      !       ! ! ! !(произвольная)!                          !
      !       !   ! !              !                          !
      !       ! ! ! ! RET          !                          !
      !       !   ! !              !                          !
      !       ! ! ! ----------------       ------------------ !
      !       !   !       A          ----->!                ! !
      !       ! ! !       !Чтение-   !     ! Процедура    * ! !
      !       !   !       !          !     !                ! !
      !       ! ! !       !запись    !     !(необязательная)! !
      !       ! ! !       !          !     !                ! !
      !       !   !       !          !  <--! RET            ! !
      !       ! ! !       V          !  !  !                ! !
      !       !   ! ---------------- !  !  ------------------ !
      !       ! ! ! !              ! !  !                     !
      !       !   ! !          CALL!------                    !
      !       ! ! ! !              !    !!                    !
      !Вызов--!---->! Модульная    !<----!                    !
      !       ! ! ! !              !    а!                    !
      !       !   ! ! процедура    !    !!                    !
      !       ! ! ! !              !    !!                    !
      !     <-!-----! RET (возврат)!    !!                    !
      !       ! ! ! !              !    !!                    !
      !       !   ! ----------------    !! ------------------ !
      !       ! ! !                    --->!                ! !
      !       !   ! ------------------ !!  ! Процедура    * ! !
      !       ! ! ! !                ! !!  !                ! !
      !       !   ! !           CALL !--!  !(необязательная)! !
      !       ! ! ! !                !  !  !                ! !
      !Вызов--!---->! Модульная      !<----! RET            ! !
      !       ! ! ! !                !     !                ! !
      !       !   ! ! процедура      !     ------------------ !
      !       ! ! ! !                !                        !
      !       ! ! ! !(необязательная)!                        !
      !       !   ! !                !                        !
      !     <-!-----! RET            !                        !
      !       !   ! !                !                        !
      !       ! ! ! ------------------                        !
      !       !   !                                           !
      --------- ! ---------------------------------------------
                !
           Интерфейс
 
      * - модульность  сохраняется по интерфейсу, хотя  процедуры
 
      могут быть не модульными.
 
                                Рис. 6
 


                                - 38 -
 
                           00152-01 97 08
 
 
           2.2. Описание интерфейса модульной процедуры
 
 
           Связь между процедурами осуществляется передачей пара-
 
      метров. Для того чтобы была полная ясность во  взаимодейст-
 
      виях между процедурами и программами, каждый параметр  дол-
 
      жен быть определен на этапе проектирования.
 
 
 
           2.2.1. Явные параметры
 
 
           Явные параметры представляют основной интерфейс проце-
 
      дуры с прочими программами. Поэтому  следует  тщательнейшим
 
      образом соблюдать правила  относительно  параметров,  соот-
 
      ветствия типов данных и механизмов передачи параметров  для
 
      обеспечения модульного  интерфейса.  Для  описания  каждого
 
      параметра используется следующий формат:
 
              имя параметра:
 
              использование:    структура данных параметра
 
              тип:              тип данных параметра
 
              доступ:           доступ параметра
 
              механизм:         механизм передачи параметра.
 
           (приложение 2 дает описание каждого из четырех атрибу-
 
      тов параметра).
 
           Чтобы сделать процедуры проще с точки  зрения  вызова,
 
      механизм передачи параметров, используемый для  конкретного
 
      типа данных, должен сохраняться одним и тем же во всех про-
 
      цедурах данного набора. Рекомендуется передавать все  неде-
 
      лимые данные по ссылке, а все строки информации - по описа-
 
      телю (дескриптору).
 


                                - 39 -
 
                           00152-01 97 08
 
 
           2.2.2. Неявные параметры
 
 
           Неявный параметр - это такой параметр, который не ука-
 
      зан в списке параметров. Неявные параметры снабжают  проце-
 
      дуру дополнительной информацией, которая черпается из ячеек
 
      области статического хранения  информации.  Существует  два
 
      вида неявных параметров:
 
           1) неявные параметры, распределяемые вызывающей  прог-
 
      раммой;
 
           2) неявные параметры, распределяемые процедурой  поль-
 
      зователя.
 
           Использование неявных  параметров  нежелательно,  пос-
 
      кольку они нарушают правила модульного программирования МОС
 
      ВП (см. приложение 1). Если не использовать  неявные  пара-
 
      метры, то легче сохранить модульность. Если процедура поль-
 
      зователя должна сохранять информацию от предыдущих  активи-
 
      заций, необходимо применить способы устранения  использова-
 
      ния неявных параметров (п. 2.2.3).
 
 
 
           2.2.2.1. Неявные параметры, распределяемые  вызывающей
 
      программой
 
 
           Вызывающая программа может разместить неявные парамет-
 
      ры в виде статически распределяемых переменных  в  поимено-
 
      ванной программной секции (PSECT) (например, COMMON и MAP в
 
      Бейсике, COMMON в Фортране или переменные,  об'явленные  во
 
      внешнем блоке процедуры или программы на Паскале). Вызываю-
 
      щая программа может также распределять неявные параметры  в
 
      виде статически распределенных глобальных переменных  (нап-
 
      ример, идентификаторы, описанные  с  помощью  пары  двоето-
 
      чий (::) в Макроассемблере, и переменные GLOBAL в Блиссе).


                                - 40 -
 
                           00152-01 97 08
 
 
           Размещение неявных  параметров  вызывающей  программой
 
      нарушает правила модульного программирования для МОС ВП  по
 
      следующим причинам:
 
           - две программы могут использовать одно и  то  же  имя
 
      PSECT или глобальную переменную с разными значениями. Такая
 
      ошибка не распознаваема;
 
           - вызывающая программа становится зависимой от вызван-
 
      ной процедуры. Следовательно,  изменение  в  одной  из  них
 
      может отрицательно повлиять на другую;
 
           - в Фортране вызывающая программа должна об'явить  все
 
      переменные как общие (COMMON) вне зависимости от числа фак-
 
      тически необходимых неявных входных параметров.  Все  пере-
 
      менные в COMMON должны быть также описаны во всех  модулях,
 
      которыми используется информация из COMMON, что  еще  более
 
      уменьшает независимость.
 
 
 
           2.2.2.2. Неявные параметры,  распределяемые  вызванной
 
      процедурой
 
 
           Неявные параметры, распределяемые  вызванной  процеду-
 
      рой, хранятся в локальной области статической памяти.
 
           Такие неявные параметры обычно используются для слеже-
 
      ния за ресурсами (с использованием  процедур  распределения
 
      ресурсов) и для сокращения списка явных параметров.  Вместе
 
      с тем, использование неявных входных параметров в  процеду-
 
      рах, не связанных с распределением ресурсов,  может  приво-
 
      дить к непредсказуемым результатам. Предположим, что проце-
 
      дура а должна предоставить информацию связанной с ней  про-
 
      цедуре B. Следовательно, у процедуры B  имеются  как  явные
 
      входные параметры (от вызывающей ее программы), так и неяв-
 


                                - 41 -
 
                           00152-01 97 08
 
 
      ные входные параметры  (из  области  памяти  процедуры  A).
 
      Затем рассмотрим ситуацию, когда вызывающая программа вызы-
 
      вает процедуру A, далее процедуру X и,  наконец,  процедуру
 
      B. Для того чтобы вызывающая программа могла получить  вер-
 
      ные результаты от процедуры B, она должна  быть  уверена  в
 
      том, что процедура X (как и любая другая процедура, к кото-
 
      рой обращается процедура X) не вызывала  процедуру  A  (так
 
      как такой вызов процедуры A приведет  к  изменению  неявных
 
      парамеров, предназначенных для процедуры B).
 
           Одна из целей модульного программирования - дать  воз-
 
      можность комбинировать процедуры произвольным  образом  без
 
      необходимости вдаваться в подробности того, как  каждая  из
 
      них работает  внутри  себя.  Именно  поэтому  использование
 
      неявных параметров приводит к нарушению  правил  модульного
 
      программирования. Те же проблемы могут возникать и в проце-
 
      дуре, не связанной с распределением ресурсов, если она сох-
 
      раняет для себя результаты своей работы в качестве  неявных
 
      параметров для последующего использования.
 
 
 
           2.2.3. Обход использования неявных параметров
 
 
           Существует три способа написания процедур, не  распре-
 
      деляющих ресурсы, в которых обходятся проблемы, связанные с
 
      использованием неявных параметров (п. 2.2.2):
 
           1) если одна  процедура получает результаты от другой,
 
      необходимо   об'единить   две   процедуры   в   один  вызов
 
      (подпункт 2.2.3.1);
 
           2) следует обеспечить отдельное обращение  к  подпрог-
 
      рамме развязки, что является способом разделения вызывающей
 
      программы во время выполнения процедуры (подпункт 2.2.3.2);
 


                                - 42 -
 
                           00152-01 97 08
 
 
           3) на вызывающую программу необходимо возложить ответ-
 
      ственность за сохранение информации по активизации процеду-
 
      ры, что осуществляется  при  помощи явного  параметра (под-
 
      пункт 2.2.3.3).
 
 
 
           2.2.3.1. Об'единение процедур
 
 
           Часто процедуры, не связанные с распределением  ресур-
 
      сов, можно об'единить в одну процедуру, которая явным обра-
 
      зом возвращает всю информацию в одном вызове.
 
           Чтобы увидеть, что дает об'единение процедур для  уст-
 
      ранения использования неявных  параметров,  можно  сравнить
 
      два примера.
 
           Пример 1.
 
      !+
      !
      ! программа демонстрирует ситуацию, когда входная информа-
      !
      ! ция процедуры зависит от выходной информации  предыдущей
      !
      ! процедуры.
      !
      !-
 
 
           REAL*4 X, Y, RESULT
 
           X = 1
 
           Y = 1
 
      !+
      !
      ! вызов процедуры, которая записывает в общую область дан-
      !
      ! ных.
      !
      !-
 
           CALL SUM_SQUARES (X, Y)
      !+
      !
      ! вызов процедуры, которая читает из общей области данных.
      !
      !-
 


                                - 43 -
 
                           00152-01 97 08
 
 
           CALL GET_SQRT (RESULT)
 
      !+
      !
      ! печать полученного результата.
      !
      !-
 
           WRITE (6,10) X, Y, RESULT
 
      10   FORMAT(1X, 'SQRT(', F6.2, '**2 +', F6.2, '**2)='.F6.2)
 
           STOP
 
           END
 
      !+
      !
      ! следующая процедура суммирует квадраты двух своих входных
      !
      ! параметров и размещает результат в общую  область для ис-
      !
      ! пользования какой-либо другой процедурой.
      !
      !-
 
           SUBROUTINE SUM_SQUARES (A, B)
 
           COMMON /INTERNAL_STORAGE/ TEMP_RESULT
 
           TEMP_RESULT = (A**2) + (B**2)
 
           RETURN
 
           END
 
      !+
      !
      ! следующая процедура вычисляет квадратный корень  числа из
      !
      ! общей  области.
      !
      !-
 
           SUBROUTINE GET_SQRT (C)
 
           COMMON /INTERNAL_STORAGE/ TEMP_RESULT
 
           C = SQRT (TEMP_RESULT)
 
           RETURN
 
           END
 
           Пример 2.
 
      !+
      !
      ! следующая процедура  показывает  подпрограммы  примера 1,


                                - 44 -
 
                           00152-01 97 08
 
 
      !
      ! об'единенные в одну; при этом  исключается  использование
      !
      ! общей  области.
      !
      !-
 
              REAL*4 X, Y, RESULT
 
              X = 1
 
              Y = 1
 
      !+                                                      
      !
      ! вызов новой процедуры.
      !
      !-
 
              CALL DO_IT_ALL (X, Y, RESULT)
 
              WRITE (6,10) X, Y, RESULT
 
      10      FORMAT (1X, 'SQRT (', F6.2, '**2 + ', F6.2, '**2)=
 
              '.F6.2)
 
              STOP
 
              END
 
      !+
      !
      ! следующая  процедура  вычисляет  квадратный  корень суммы
      !
      ! квадратов своих первых двух аргументов и выдает результат
      !
      ! KAK  третий  параметр. Она  об'единяет функции процедур и
      !
      ! исключает использование общей области.
      !
      !-
 
              SUBROUTINE DO_IT_ALL (A, B, C)
 
              C = SQRT ((A ** 2) + (B ** 2))
 
              RETURN
 
              END


                                - 45 -
 
                           00152-01 97 08
 
 
           2.2.3.2. Пользовательская программа развязки
 
 
           Еще один способ об'единения ряда процедур в одну  зак-
 
      лючается в предоставлении вызывающей программе  возможности
 
      получения управления в критической точке выполнения  проце-
 
      дуры. Для того чтобы такое могло произойти, процедура поль-
 
      зователя должна задать аргумент программы развязки, которая
 
      будет вызываться в ходе выполнения. Таким образом, процеду-
 
      ра пользователя может выполняться  дважды:  перед  и  после
 
      программы развязки без каких бы то ни было неявных парамет-
 
      ров (входных). В операторах OPEN Бейсика, Фортрана и паска-
 
      ля используется именно такая техника, что позволяет пользо-
 
      вателю указать свою программу развязки.
 
           Чтобы вызывающая программа избежала неявных  входов  в
 
      свою  программу  развязки,  процедура  пользователя  должна
 
      обеспечивать свой аргумент для передачи программе  развязки
 
      (п. 3.1.6). Вызывающая программа использует следующую вызы-
 
      вающую последовательность для вызова процедуры  пользовате-
 
      ля:
 
               CALL MY-PROC (... , ACTION-ROUTINE, USER-ARG)
 
           Затем процедура пользователя вызывает  программу  раз-
 
      вязки:
 
               CALL ACTION-ROUTINE (... ,USER-ARG)
 
 
 
           2.2.3.3. Возложение функций сохранения  информации  на
 
      вызывающую программу
 
 
           Можно сделать так, чтобы  вызывающая  программа  несла
 
      ответственность за сохранение информации от одной активиза-
 
      ции процедуры до другой. Можно применить следующих три спо-
 
      соба:


                                - 46 -
 
                           00152-01 97 08
 
 
           1) потребовать от  вызывающей  программы  распределять
 
      память, необходимую процедуре. Затем  вызывающая  программа
 
      передает адрес ячейки памяти в  качестве  явного  параметра
 
      при всех вызовах процедуры. Недостаток данного способа зак-
 
      лючается в том, что нельзя увеличить об'ем памяти,  который
 
      необходим процедуре, не переписав все вызывающие программы.
 
      Следовательно, данным способом следует пользоваться  только
 
      тогда, когда есть уверенность в том, что процедура не будет
 
      в будущем переделываться в целях использования дополнитель-
 
      ного пространства памяти;
 
           2) потребовать от вызывающей программы выделить  место
 
      под указатель (двойное слово) хранимой информации  и  пере-
 
      дать его адрес процедуре в качестве явного  параметра.  При
 
      первом  вызове  вызванная  процедура  динамически   выделит
 
      память  для   хранения   информации   (посредством   вызова
 
      LIB$GET_VM) и поместит ее адрес в двойное слово  вызывающей
 
      программы. При последующих вызовах процедура  воспользуется
 
      информацией, сохранившейся в памяти от предыдущих вызовов;
 
           3) потребовать от вызывающей программы передавать про-
 
      цедуре значение, идентифицирующее в рамках процесса.  Такой
 
      идентификатор в рамках процесса указывает, какая информация
 
      из предшествующих активизаций  процедуры  должна  использо-
 
      ваться как неявные входные параметры.
 
           На рис. 7 приведена вызывающая  программа,  отвечающая
 
      за явное указание той области памяти, которая будет исполь-
 
      зоваться вызванной процедурой.
 
 
 
 
 
 
 
 


                                - 47 -
 
                           00152-01 97 08
 
 
          ------------ :к
          !          !  !
          !Память для!***********************
          !          !  !                   *
          !вызывающей!                      *
          !          !  !                   *
          !программы !<********  -----------*--------------------
          !          !  !     *  !          *                   A
          ------------        *  !  --------*-------------------!
                        !     *  !  !       *                  !!
      ----------------        *  !  !       *                  !!
      !              !     ---------------- *  ------------ :L !!
      !              !  !  !              ! *  !          !    !!
      !CALL READ (K)------>!READ          ! *  !Память для!    !!
      !              !  !  !              ! *  !          !    !!
      !            <-------!RET           !***>!процедуры !    !!
      !              !  !  !              ! *  !          !    !!
      !              !     ---------------- *  !    X     !    !!
      !              !  !                   *  !          !    !!
      !              !        Процедура     *  ------------    !!
      !              !  !                   *                  !!
      !              !                   **** ---------------- !!
      !              !  !                *    !              ! !!
      !CALL X      ----------------------*--->! X            ! !!
      !              !  !                *    !              ! !!
      !            <---------------------*----!CALL READ (L) !<-!
      !              !  !                V  ! !              !  !
      !              !     ---------------- !-!RET           !  !
      !              !  !  !              !   !              !---
      !CALL GET (K)------->!GET           !   ----------------
      !              !  !  !              ! !
      !            <-------!RET           !     Процедура
      !              !     !              ! !
      !              !  !  ----------------
      !              !                      !
      !              !  !    Процедура
      ----------------                      !
                        !               Интерфейс
       Вызывающая
                        !
       программа
                        !
                    Интерфейс
 
      **> путь передачи информации
 
      --> передача управления
 
           Предоставляя ответственность за память для информации
 
      вызывающей программе, можно разделить информацию, которая
 
      запоминается при каждой активизации процедуры, и избежать
 
      нераспознаваемых конфликтных ситуаций.
 
                                Рис. 7
 


                                - 48 -
 
                           00152-01 97 08
 
 
           2.2.3.4. Выделение   памяти    процедуре    вызывающей
 
      программой
 
 
           При данном способе вызывающая программа выделяет  про-
 
      цедуре всю необходимую память и  передает  адрес  памяти  в
 
      виде явного параметра при каждом вызове процедуры.
 
           Например, для библиотечной процедуры  MTH$RANDOM  тре-
 
      буется, чтобы  вызывающая  программа  выделила  память  под
 
      начальное значение (длинное слово) и передавала  его  адрес
 
      при каждом  вызове.  Процедура  MTH$RANDOM  использует  его
 
      содержимое в качестве входного значения и вычисляет следую-
 
      щее случайное число (последовательность) по текущему значе-
 
      нию. Процедура  MTH$RANDOM  возвращает  случайное  число  в
 
      интервале между 0 и 1. Она также изменяет содержимое  двой-
 
      ного слова, которое передается  ей  вызывающей  программой.
 
      Этим обеспечивается то, что при следующем вызове  процедура
 
      сгенерирует отличающееся значение.
 
 
 
           2.2.3.5. Передача вызывающей программой указателя
 
 
           При данном способе вызывающая программа размещает лишь
 
      указатель (размером в двойное слово) динамически собираемой
 
      памяти, которую распределяет процедура пользователя.  Затем
 
      адрес указателя передается процедуре в виде явного парамет-
 
      ра. Существует два способа  для  указания  инициализируемой
 
      памяти:
 
           1) задается единственная точка входа.  Если  вызванная
 
      процедура обнаруживает нулевое значение в указателе,  выде-
 
      ленном вызывающей программой, процедура распределяет и ини-
 
      циализирует динамически собираемую память;
 
           2) задается вспомогательная точка входа. Данная  точка


                                - 49 -
 
                           00152-01 97 08
 
 
      содержит адрес (длинное слово) выделенного участка  памяти.
 
      При последовательных вызовах процедура использует это  зна-
 
      чение в качестве адреса памяти с информацией от  предыдущих
 
      вызовов.
 
           Независимо от  метода,  использованного  для  указания
 
      распределения и инициализации памяти, следует также предус-
 
      мотреть способ указания необходимости освобождения  памяти.
 
      Сделать последнее можно с помощью отдельного параметра либо
 
      отдельной точки входа.
 
           Например, процедура LIB$INIT_TIMER,  которая  получает
 
      информацию об отсчете времени и о  содержимом  счетчика  из
 
      операционной системы, использует единственный  необязатель-
 
      ный параметр HANDLE-ADR для определения того,  где  следует
 
      хранить эту информацию. Параметр  HANDLE-ADR  -  это  адрес
 
      (длинное слово), указывающий блок памяти, в котором  содер-
 
      жатся значения отсчетов времени и счетчиков:
 
           - если параметр HANDLE-ADR отсутствует, величины поме-
 
      щаются в статической области памяти,  тем  самым  превращая
 
      настоящий вызов не повторновходимым с точки зрения обработ-
 
      ки асинхронных системных прерываний;
 
           - если  параметр  HANDLE-ADR  нулевой,  LIB$INIT_TIMER
 
      выделяет  блок  динамической  массовой  памяти  посредством
 
      вызова процедуры LIB$GET_VM.  Значения  помещаются  в  этот
 
      блок, а адрес блока возвращается в параметре HANDLE-ADR;
 
           - если значение параметра HANDLE-ADR отлично от  нуля,
 
      считается, что это значение -  адрес  блока  памяти,  ранее
 
      выделенной в результате вызова LIB$INIT_TIMER.  Далее  блок
 
      будет использоваться снова, и новые отсчеты времени и счет-
 
      чиков будут помещены в него.
 
           Процедура LIBB$FREE_TIMER освобождает блок  динамичес-


                                - 50 -
 
                           00152-01 97 08
 
 
      кой массовой памяти, который был выделен в результате пред-
 
      шествующего  вызова  процедуры   LIB$INIT_TIMER.   Параметр
 
      HANDLE-ADR процедуры LIB$FREE_TIMER -  это  адрес  (длинное
 
      слово), который указывает блок динамической массовой  памя-
 
      ти, в котором хранятся отсчеты времени и  счетчиков.  Такая
 
      память возвращается в область свободной памяти в результате
 
      вызова процедуры LIB$FREE_VM.
 
 
 
           2.2.3.6. Передача        вызывающей         программой
 
      идентификатора, имеющего смысл в рамках процесса
 
 
           При данном способе вызывающая программа передает  зна-
 
      чение, имеющее вполне определенный смысл в рамках  процесса
 
      и служащее для идентификации неявных результатов, порожден-
 
      ных предыдущими вызовами  и  являющихся  неявными  входными
 
      параметрами для данного вызова. Любая вызывающая  программа
 
      может использовать идентификатор в рамках процесса.  Приме-
 
      рами идентификаторов,  имеющих  смысл  в  рамках  процесса,
 
      могут служить номера логических устройств в языках Бейсик и
 
      Фортран и номера каналов ввода-вывода  программ  системного
 
      обслуживания системы МОС ВП.
 
           Идентификаторы,  имеющие  смысл  в  рамках   процесса,
 
      представляют некоторый ресурс. Техника модульного  програм-
 
      мирования требует, чтобы все ресурсы, распределяемые проце-
 
      дурой, распределялись посредством вызова процедуры  распре-
 
      деления (выделения) ресурсов. Этим предотвращается  возник-
 
      новение  конфликтных  ситуаций,  поскольку  одна  процедура
 
      может отслеживать множество выделений ресурсов при  активи-
 
      зации более чем одной процедуры. Поэтому  необходимо  напи-
 
      сать процедуру распределения ресурсов и поместить ее в биб-
 


                                - 51 -
 
                           00152-01 97 08
 
 
      лиотеку об'ектных модулей для использования  другими  прог-
 
      раммистами.
 
           Библиотечные  процедуры  LIB$GET_LUN  и   LIB$FREE_LUN
 
      выделяют и освобождают номера логических устройств в языках
 
      Фортран и Бейсик вне стандартного диапазона номеров,  зада-
 
      ваемых в программах пользователей, то  есть  вне  диапазона
 
      от 0 до 99.
 
 
 
           2.2.4. Порядок расположения параметров
 
 
           Процедуры исполнительной библиотеки  следуют  согласо-
 
      ванному порядку следования параметров. Необходимо группиро-
 
      вать параметры процедуры слева направо в таком порядке:
 
           1) обязательные входные параметры (доступ для чтения);
 
           2) обязательные  параметры  ввода-вывода  (доступ  для
 
      модификации);
 
           3) обязательные выходные параметры (доступ  для  запи-
 
      си);
 
           4) дополнительные (необязательные)  входные  параметры
 
      (доступ для чтения);
 
           5) необязательные параметры ввода-вывода  (доступ  для
 
      мо икации);
 
           6) необязательные входные параметры (доступ для  запи-
 
      си).
 
           Необязательные  параметры  следуют  за   обязательными
 
      параметрами. Поэтому, когда вызывающая  программа  опускает
 
      необязательные параметры, список действительных параметров,
 
      передаваемый процедуре, сокращается.
 
           Вызываемая процедура  получает  доступ  к  необходимым
 
      параметрам слева  направо,  начиная  с  первого  параметра.
 


                                - 52 -
 
                           00152-01 97 08
 
 
      единственным исключением являются процедуры, которые  возв-
 
      ращают значение функции, которое больше 64 битов, например,
 
      строки или значения с плавающей запятой  формата  H.  Боль-
 
      шинство значений функций возвращается в первые два регистра
 
      R0, R1. (это делается  автоматически  для  языков  высокого
 
      уровня). Однако при значениях, больших 64 битов, это трудно
 
      сделать. В этом случае вызывающая программа использует пер-
 
      вый параметр для указания, где разместить значения функции,
 
      а другие параметры получаются  сдвинутыми  вправо  на  одну
 
      позицию [5].
 
 
 
           2.2.5. Использование необязательных параметров
 
 
           Необязательный параметр - это такой параметр,  который
 
      вызывающая программа может опустить.  Вызывающая  программа
 
      указывает отсутствие параметров передачей элементов  списка
 
      параметров, содержащих нули. В случае  последнего  необяза-
 
      тельного параметра вызывающая программа может передать уко-
 
      роченный список либо нулевой элемент списка параметров.
 
           Нулевой элемент списка параметров - это  просто  нуль,
 
      переданный процедуре посредством значения.  Например,  если
 
      вызвать процедуру, именуемую GRA_GUBE, и опустить  необяза-
 
      тельный параметр C, вызывающая последовательность для  бэй-
 
      сика будет иметь вид:
 
               15 CALL GRA_GUBE(A, B, 0 BY VALUE)
 
      в данном вызове "0 BY VALUE" - нулевой элемент списка пара-
 
      метров.
 
           Примечание. Большинство программ системного обслужива-
 
      ния системы МОС ВП в  отличие  от  процедур  исполнительной
 
      библиотеки не могут воспринимать укороченный перечень пара-
 


                                - 53 -
 
                           00152-01 97 08
 
 
      метров. Опущенные параметры должны всегда указываться нуле-
 
      выми элементами.
 
           Для параметров, передаваемых по значению, нет  отличия
 
      в передаче нулевого значения и передаче  нулевого  элемента
 
      списка параметров.
 
 
 
           2.3. Входные точки JSB
 
 
           Не рекомендуется пользоваться входными точками  JSB  в
 
      процедурах, которые будут помещены в  библиотеку  процедур.
 
      Процедуры, которые могут быть вызваны  только  инструкциями
 
      JSB, не могут вызываться из языков высокого  уровня.  Такие
 
      процедуры не соответствуют принятым в системе МОС ВП прави-
 
      лам вызова процедур и обработки условий. Если процедура все
 
      же использует входную точку JSB, в ней  также  должна  быть
 
      эквивалентная входная точка вызова в целях соблюдения неза-
 
      висимости от языка  программирования.  Такая  точка  должна
 
      быть, т. к. команда JSB разрешена только в  Макроассемблере
 
      и Блисс. Если в процедуре есть входная точка  JSB,  ее  имя
 
      должно состоять из имени процедуры и на конце _RN. N указы-
 
      вает наибольший  по  номеру  регистр,  содержимое  которого
 
      изменяется, или который используется  в  качестве  входного
 
      параметра.
 
           Например,   входной   точкой   JSB    для    процедуры
 
      LIB$ANALYZE_SDESC   исполнительной   библиотеки    является
 
      LIB$ANALYZE_SDESC_R2.
 


                                - 54 -
 
                           00152-01 97 08
 
 
           2.4. Использование ресурсов системы
 
 
           Доступные пользователю системные ресурсы ограничивают-
 
      ся его квотами учета и  количеством  доступных  ресурсов  в
 
      системе.  Эффективное  использование   системных   ресурсов
 
      делает большую часть ресурсов доступной всем процессам.
 
 
 
           2.4.1. Выбор типа памяти
 
 
           Существует три типа памяти для хранения информации:
 
           1) статическая память;
 
           2) стековая;
 
           3) массовая.
 
           Три формы хранения отличаются по способу  и  продолжи-
 
      тельности закрепления, то есть по тому, сколь  долго  можно
 
      использовать такую память.
 
 
 
           2.4.1.1. Стековая память
 
 
           Процедура занимает память в стеке  процесса  во  время
 
      прогона задачи. Процедура делает это динамически,  по  мере
 
      необходимости. Занимая стековую  память,  процедура  "сдви-
 
      гает" указатель стека "вверх", уменьшая его  значение.  При
 
      возврате управления вызывающей программе процедура освобож-
 
      дает место в стеке, сдвигая указатель стека "вниз"  (увели-
 
      чивая его значение). Стековая память существует  только  на
 
      время активизации процедуры, которая и создает эту память.
 
           Стековая память используется, когда результат  необхо-
 
      дим только для активизации текущей процедуры. Она  освобож-
 
      дается, когда процедура  возвращает  управление  вызывающей
 
      программе.
 


                                - 55 -
 
                           00152-01 97 08
 
 
           2.4.1.2. Массовая память
 
 
           Динамическая массовая память выделяется во время  про-
 
      гона из пула процесса, как только при активизации процедуры
 
      в этом возникает потребность и как  только  квоты  учета  и
 
      виртуальное адресное пространство  процесса  позволяют  это
 
      сделать.
 
           Для получения массовой памяти  процедура  пользователя
 
      вызывает  системную  подпрограмму,  такую   как   процедура
 
      LIB$GET_VM исполнительной библиотеки или программа  систем-
 
      ного обслуживания  $EXPREG.  Вызов  системной  подпрограммы
 
      может быть внутри самой процедуры, либо можно  использовать
 
      универсальную процедуру распределения ресурса для централи-
 
      зованного распределения ресурсов.
 
           Массовая память освобождается, то есть возвращается  в
 
      пул процесса, посредством вызова LIB$FREE_VM. Для  освобож-
 
      дения массовой памяти нельзя использовать программу систем-
 
      ного обслуживания $CNTREG.
 
           Массовая память используется, когда необходимый  об'ем
 
      памяти изменяется от вызова к  вызову  и  когда  результаты
 
      сохраняются для последующей активизации  процедуры.  Память
 
      освобождается  перед  возвращением  управления   вызывающей
 
      программе (посредством вызова процедуры LIB$FREE_VM).
 
 
 
           2.4.1.3. Статическая память
 
 
           Во время компоновки компоновщик системы МОС ВП  сосре-
 
      доточит память аналогичных программных секций PSECT в  одну
 
      секцию образа. Начальное содержимое такой  памяти  задается
 
      исходным текстом программы.  Компоновщик  проинициализирует
 
      нулями всякую неинициализированную статическую память.  При


                                - 56 -
 
                           00152-01 97 08
 
 
      вызове процедуры  после  инициализации  статическая  память
 
      будет иметь то же местоположение, а  содержимое  ее  сохра-
 
      ниться от предыдущего вызова.
 
           Статическая память используется, когда необходимо сох-
 
      ранить результаты для будущей активизации процедуры.
 
           Примечание. Тип памяти может определяться по  длитель-
 
      ности и/или количеству хранимой  информации.  Любая  память
 
      для хранения информации в  течение  длительного  времени  и
 
      неизвестных об'емов на этапе компиляции должна быть  массо-
 
      вой памятью. Для кратковременного  хранения  информации  (в
 
      течение текущего  вызова  процедуры)  следует  использовать
 
      стековую память. Для длительного хранения информации, кото-
 
      рая нужна только в отдельном случае,  следует  использовать
 
      статическую память.
 
 
 
           2.4.1.4. Обход использования статической памяти
 
 
           В использовании статической памяти имеется ряд  недос-
 
      татков, а именно:
 
           - статическая память представляет неэффективный способ
 
      использования  памяти.   При   использовании   статического
 
      варианта хранения информации  следует  обеспечивать  макси-
 
      мально возможное по об'ему использование памяти;
 
           - из-за неэффективности  использования  памяти  образы
 
      будут больших размеров;
 
           - использование статического варианта  хранения  может
 
      приводить к проблемам, связанным  с  реентерабельностью  по
 
      AST, что иллюстрирует пример. В  данном  примере  обходится
 
      проблема разрушения информации асинхронного системного пре-
 
      рывания за счет установки флага первого  обращения.  Другим
 


                                - 57 -
 
                           00152-01 97 08
 
 
      способом для решения этой проблемы является
 
      использование  инструкции  "проверить и  установить"  (под-
 
      пункт 3.3.4.2).
 
           Пример.
 
      10    !+
            !
            ! программа для демонстрации порчи статической памяти
            !
            ! в результате AST.
            !
            !-
 
            DECLARE LONG CURRENT_NUMBER
 
            !+
            !
            ! разрешение обработки AST, связанного с нажатием
            !
            ! CTRL/C.
            !
            !-
 
            ON ERROR GOTO 19000
 
            X% = CTRLC
 
            !+
            !
            ! увеличить число и отмечать текущее значение. Когда
            !
            ! число достигнет значения 1000, - завершить програм-
            !
            ! му.
            !
            !-
 
            FOR CURRENT_NUMBER = 1% TO 1000%
 
      100   PRINT CURRENT_NUMBER;
 
            NEXT CURRENT_NUMBER
 
            GOTO 32767
 
      19000 !+
            !
            ! подрограмма обработки ошибок. Если вход в эту под-
            !
            ! программу происходит по AST вследствии ввода
            !
            ! CTRL/C, портится значение CURRENT_NUMBER установкой
            !
            ! его в -1.
            !
            !-


                                - 58 -

                           00152-01 97 08
 
 
            !
            IF ERR = 28 THEN CURRENT_NUMBER = -1%
 
            RESUME 100
 
      32767 END
 
 
           2.4.1.5. Обзор используемых в языках  программирования
 
      способов хранения информации
 
 
           В табл. 6 сведены варианты хранения  информации,  дос-
 
      тупные программисту в процедурах, написанных  на  различных
 
      языках программирования.
 
                                                       Таблица 6
 
               Обзорная таблица по использованию типов
 
                  памяти в языках программирования
 
      ----------------------------------------------------------
               !
      Язык про-!                Тип памяти
               !
      граммиро-!------------------------------------------------
               !                   !               !
      вания    ! Статическая       ! Стековая      !  Массовая
               !                   !               !
      ----------------------------------------------------------
               !                   !               !
      АДА      ! Константы и об'ек-! Локальные пе- ! оО'екы с
               !                   !               !
               !ты фиксированного  !ременные под-  !динамически
               !                   !               !
               !размера, содержа-  !программ и за- !назначаемыми
               !                   !               !
               !щиеся в пакетах    !дач            !размерами в
               !                   !               !
               !библиотек          !               !пакетах биб-
               !                   !               !
               !                   !               !лиотек и
               !                   !               !
               !                   !               !об'екты, соз-
               !                   !               !
               !                   !               !данные рас-
               !                   !               !
               !                   !               !пределителями
               !                   !               !
      Бейсик   ! Вся информация,   ! Локальные     ! Динамические
               !                   !               !
               !хранящаяся в       !переменные     !строки,
               !                   !               !
               !COMMON и MAP       !               !исполняемые
               !                   !               !


                                - 59 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 6
      ----------------------------------------------------------
               !
      Язык про-!                Тип памяти
               !
      граммиро-!------------------------------------------------
               !                   !               !
      вания    ! Статическая       ! Стековая      !  Массовая
               !                   !               !
      ----------------------------------------------------------
               !                   !большинство    !операторы
               !                   !               !
               !                   !массивов       !DIMENSION
               !                   !               !
      Блисс    ! OWN и GLOBAL      ! STACK LOCAL   ! При вызове
               !                   !               !
               !                   !               !LIB$GET_VM
               !                   !               !
      Кобол    ! Запоминание всех  ! Неприменимо   ! При вызове
               !                   !               !
               !данных             !               !LIB$GET_VM
               !                   !               !
      Форкран  ! Запоминание всех  ! Неприменимо   ! При вызове
               !                   !               !
               !данных             !               !LIB$GET_VM
               !                   !               !
      Макро    ! Запоминание бло-  ! Уменьшение    ! При вызове
               !                   !               !
               !ков                !указателя      !LIB$GET_VM
               !                   !               !
               !                   !стека          !
               !                   !               !
      Паскаль  ! Вся информация    ! Локальные     ! При вызове
               !                   !               !
               !уровня прог-       !данные         !NEW *)
               !                   !               !
               !раммы или          !PROCEDURE      !
               !                   !               !
               !модуля             !и FUNCTION     !
               !                   !               !
      ПЛ/1     ! STATIC            ! AUTOMATIC     ! Оператор
               !                   !               !
               !                   !               !ALLOCATE
               !                   !               !
               !                   !               !(BASED)**)
 
           Примечания:
 
           1.*) существуют другие правила, которыми  можно  также
 
      определить вариант хранения (статический или в стеке).
 
           2.**) BASED - это класс памяти, который используется в
 
      языке ПЛ/1  для  распределения  массовой  памяти.  Командой
 
      ALLOCATE производится фактическое распределение.
 


                                - 60 -
 
                           00152-01 97 08
 
 
           2.4.2. Использование флагов событий
 
 
           Флаги событий позволяют модульным  процедурам  обмени-
 
      ваться сообщениями и синхронизировать свою работу. Посколь-
 
      ку флаги событий можно распределить на этапе прогона,  про-
 
      цедура может прогоняться  независимо  от  других  процедур,
 
      существующих в том же процессе.
 
           Флаги событий распределяются и освобождаются  процеду-
 
      рами     исполнительной     библиотеки     LIB$GET_EF     и
 
      LIB$FREE_FF [1].
 
 
 
           2.4.3. Использование номеров логических устройств
 
 
           Номер логического устройства используется для описания
 
      устройства или  файла,  который  программа  использует  для
 
      выполнения операции ввода и  вывода.  Модульным  процедурам
 
      нет необходимости знать номера устройств  других  процедур,
 
      работающих одновременно с ними.
 
           Номера логических устройств используются только в бэй-
 
      сике и Фортране.
 
           Распределение и освобождение номеров  логических  уст-
 
      ройств должно выполняться с помощью процедур LIB$GET_LUN  и
 
      LIB$FREE_LUN исполнительной библиотеки [1].
 
 
 
           2.5. Использование ввода-вывода
 
 
           В общем случае ввод-вывод  процедуры  будет  направлен
 
      либо на экран терминала, либо в файл. (в некоторых  случаях
 
      может потребоваться ввод-вывод через почтовый ящик и  сете-
 
      вые операции обмена [6]. Независимо от того, имеет ли прог-
 
      рамма пользователя отношение к вводу-выводу на экран терми-
 


                                - 61 -
 
                           00152-01 97 08
 
 
      нала или в файл, существует два  правила,  которых  следует
 
      придерживаться в целях соблюдения модульности:
 
           1) процедура не должна выводить на печать сообщения об
 
      ошибках или информационного назначения ни  непосредственно,
 
      ни путем вызова программы $PUTMSG системного  обслуживания.
 
      Процедура должна либо вернуть значение условия в регистр R0
 
      как значение функции, либо вызвать LIB$SIGNAL или  LIB$STOP
 
      для вывода всех сообщений (процедуры LIB$SIGNAL и  LIB$STOP
 
      могут вызываться как явно, так и косвенно (неявно));
 
           2) процедура должна использовать независящие  от  уст-
 
      ройства средства обслуживания и  процедуры  для  выполнения
 
      операций ввода-вывода.
 
 
 
           2.5.1. Ввод-вывод с терминала
 
 
           К средствам, которые можно использовать для выполнения
 
      обмена с терминалом, относятся следующие:
 
           1) программа системного обслуживания очереди  запросов
 
      на ввод-вывод ($QIO). Использование $QIO для  осуществления
 
      обмена с терминалом весьма эффективно, хотя это также весь-
 
      ма трудоемкий способ  реализации  обмена.  $QIO  использует
 
      зависящие от устройства средства  обслуживания  и  является
 
      наиболее сложным для обращения из программ на языках  высо-
 
      кого уровня по сравнению с остальными рассматриваемыми спо-
 
      собами, поскольку требует большего числа шагов, а интерфейс
 
      вызова предполагает больше информации со стороны вызывающей
 
      программы, чем в случае использования средств  СУД-32.  При
 
      использовании $QIO в процедуре может  потребоваться  выпол-
 
      нить ряд шагов. Они могут включать создание списков сообще-
 
      ний, написание подпрограмм обработки асинхронных  системных
 


                                - 62 -
 
                           00152-01 97 08
 
 
      прерываний, присваивание канала ввода-вывода, постановку  в
 
      очередь запроса на ввод-вывод, проверки  успешности  поста-
 
      новки запроса в очередь и завершения операции обмена, осво-
 
      бождение канала ввода-вывода. $QIO желательно  использовать
 
      для реализации того, что просто нельзя  сделать  с  помощью
 
      СУД-32 [2];
 
           2) СУД-32. Средства СУД-32 не зависят от устройства  и
 
      предоставляют средства обслуживания универсального назначе-
 
      ния, к которым проще обращаться, чем к $QIO. Вместе с  тем,
 
      часто не удобно в программах на языках высокого уровня фор-
 
      мировать блоки управления доступом (блок доступа  к  файлу,
 
      блок доступа к  записи  и  т.д.),  которые  необходимы  для
 
      средств СУД-32 [4];
 
           3) операторы ввода-вывода языков программирования.  Во
 
      всех языках программирования высокого уровня имеются опера-
 
      торы ввода-вывода. Такими операторами  легко  пользоваться,
 
      они обеспечивают простой обмен и форматирование данных  для
 
      пользователей, пишущих программы на языке высокого  уровня,
 
      и являются самым простым  из  возможных  способов.  Наличие
 
      естественных  операторов  ввода-вывода  в  языках  высокого
 
      уровня освобождает  пользователя  от  необходимости  непос-
 
      редственно обращаться к средствам $QIO  или  СУД-32:  такие
 
      вызовы реализуются скомпилированной  программой.  В  то  же
 
      время в языках низкого и среднего уровня (Макроассемблере и
 
      Блисс)  отсутствуют  встроенные  в  язык  операторы  ввода-
 
      вывода, и  приходится  использовать  средства  обслуживания
 
      $QIO и СУД-32 для ввода-вывода с терминала и в файл;
 
           4) процедуры  обслуживания  экрана  из  исполнительной
 
      библиотеки (SMG$). Процедуры группы SMG$ предоставляют лег-
 
      ко реализуемый интерфейс для программ, написанных на языках


                                - 63 -
 
                           00152-01 97 08
 
 
      высокого уровня. Эти процедуры не зависят от  устройства  и
 
      помогают составлять  сложные  экранные  образы.  Средствами
 
      группы SMG$ исполнительной библиотеки обеспечивается  режим
 
      "окно", то есть деление экрана  на  многочисленные  поля  и
 
      выполнение операций манипулирования с такими полями.  Среди
 
      прочих  возможностей,  обеспечиваемых  процедурами   группы
 
      SMG$, есть следующие [1]:
 
           - вывод информации на виртуальные устройства отображе-
 
      ния;
 
           - ввод информации с виртуальной клавиатуры;
 
           - возможность выполнения асинхронного ввода;
 
           - встроенные средства минимального обновления экрана;
 
           - необязательные буферизация и  пакетная  обработка  в
 
      целях оптимизации производительности;
 
           - возможность прерывать рассылаемые сообщения;
 
           - возможность выполнить вывод в файл или на устройство
 
      получения твердой копии;
 
           - обслуживание терминалов, не входящих в комплект пос-
 
      тавки СМ 1700.
 
           При обмене с терминалом важным моментом  является  то,
 
      чтобы процедура и головная программа согласованно  участво-
 
      вали в управлении экраном  терминала.  Например,  процедура
 
      ввода-вывода может вывести что-то  на  экран  терминала,  а
 
      вызывающая программа желает такую информацию стереть. Вызы-
 
      вающая программа должна знать как о том, какого вида инфор-
 
      мация, так и о том, где она располагается, чтобы  ее  можно
 
      было стереть. Вызывающая программа  и  вызванная  процедура
 
      должны быть связаны посредством механизма передачи парамет-
 
      ров, чтобы определить, к какой части экрана каждая  из  них
 
      будет осуществлять доступ. Именно для этих целей в исполни-


                                - 64 -
 
                           00152-01 97 08
 
 
      тельной библиотеке находятся процедуры обслуживания  экрана
 
      (группа SMG$).
 
           Важно, чтобы внутри программы пользователя не применя-
 
      лись различные способы ввода-вывода. Могут возникнуть проб-
 
      лемы, если в вызывающей  программе  и  вызванной  процедуре
 
      используются различные  способы  ввода-вывода.  При  каждом
 
      способе выполнения  обмена  используется  некоторое  знание
 
      того, что в данный момент находится на экране терминала.  В
 
      крайнем случае запоминается текущее  положение  курсора  на
 
      экране. При вводе-выводе иного  вида  такая  информация  не
 
      изменяется и, следовательно, становится неверной. Результа-
 
      ты любой следующей операции  ввода-вывода  становятся  неп-
 
      редсказуемыми.
 
 
 
           2.5.2. Ввод-вывод из файла
 
 
           Операции обмена информацией с файлом могут выполняться
 
      одним из следующих способов:
 
           1) с помощью СУД-32. СУД-32 предоставляет  возможность
 
      использовать разнообразные организации файлов и режимы дос-
 
      тупа на чтение, из которых можно выбрать наиболее  подходя-
 
      щий для данной  программы  пользователя  способ  обработки.
 
      СУД-32  обслуживает  файлы  с  последовательной,  прямой  и
 
      индексно-последовательной организацией. Такие режимы позво-
 
      ляют осуществлять доступ к записям файлов  последовательно,
 
      произвольно по значению ключа либо по относительному номеру
 
      записи, либо произвольно по адресу записи  в  файле  (RFA).
 
      Обычно  нет  необходимости  непосредственно  обращаться   к
 
      средствам СУД-32 из программ, написанных на языках высокого
 
      уровня [4];
 


                                - 65 -
 
                           00152-01 97 08
 
 
           2) вводом-выводом на уровне операторов языка  програм-
 
      мирования. В большинстве языков высокого уровня скомпилиро-
 
      ванная программа будет вызывать для выполнения работ с фай-
 
      лами процедуру поддержки языка из исполнительной  библиоте-
 
      ки. Процедуры  исполнительной  библиотеки  обычно  вызывают
 
      средства СУД-32. Таким образом, большинство средств  СУД-32
 
      доступны пользователю, пишущему программы на языке высокого
 
      уровня, без непосредственного обращения к СУД-32. Операторы
 
      ввода-вывода языков программирования могут применяться либо
 
      для файлов данных, либо для выходных (выводимых) файлов.  В
 
      языках низкого и среднего уровня (Макроассемблере и  Блисс)
 
      нет операторов ввода-вывода,  и  программы,  написанные  на
 
      таких языках, должны обращаться к средствам СУД-32 сами.
 
 
 
           2.6. Документирование
 
 
           Каждую процедуру следует  документировать  (с  помощью
 
      программных комментариев) тщательнейшим образом с тем, что-
 
      бы все пользователи знали, что выполняет данная  процедура.
 
      В большинстве случаев модуль должен содержать  только  одну
 
      процедуру.
 
 
 
           2.6.1. Описание модуля
 
 
           В начале каждого модуля желательно расположить в  виде
 
      предисловия следующую информацию:
 
           1) заглавие - задает имя модуля, за которым следует  в
 
      виде одной строки описание его функционального назначения;
 
           2) версия - указывает версию и номер редакции  в  виде
 
      трехзначного числа.  Обычно  1-001  соответствует  исходной
 
      версии;


                                - 66 -
 
                           00152-01 97 08
 
 
           3) средства - дает  описание  библиотечного  средства,
 
      например, библиотека обслуживающих программ общего назначе-
 
      ния (LIB);
 
           4) краткое описание - дает краткое описание (три-шесть
 
      строк) функционального назначения модуля;
 
           5) среда функционирования - перечисляются любые особые
 
      допущения на условия, в которых может работать модуль. Сюда
 
      входят допущения, относящиеся как к этапу компиляции, так и
 
      к этапу выполнения, которые могут влиять либо  на  аппарат-
 
      ные, либо на программные средства системы.  Описываются  те
 
      ситуации, которые предполагаются при выполнении  модуля,  и
 
      описываются те необязательные  элементы  правил  модульного
 
      программирования в системе МОС ВП, которым данный модуль не
 
      соответствует. Указываются характеристски реентерабельности
 
      для входящих в модуль процедур. Каждая процедура будет либо
 
      полностью реентерабельной,  либо  реентерабельной  с  точки
 
      зрения асинхронных системных прерываний, либо не  реентера-
 
      бельной;
 
           6) автор - указывается фамилия автора и дата  создания
 
      модуля;
 
           7) изменения - указывается  номер  изменения,  фамилия
 
      программиста, осуществляющего изменения, дату  изменений  и
 
      перечень изменений.
 
           Этим завершается предисловие. В конце предисловия ста-
 
      вится символ - разделитель страниц. За предисловием следует
 
      действительный код модуля.
 
           Описание модуля иллюстрируется на примере:
 
      PROGRAM CRA_CUBE       ! создать представление (образ) куба
 
      !+
      !
      ! версия     1-002


                                - 67 -
 
                           00152-01 97 08
 
 
      !
      ! используемые средства: пользовательская библиотека вычис-
      !
      !                        лительных и графических процедур
      !
      ! краткое описание:      данный модуль содержит процедуру
      !
      !                        формирования математического опи-
      !
      !                        сания куба GRA_CUBE
      !
      ! среда:                 пользовательский режим, реентера-
      !
      !                        бельность по AST
      !
      ! автор:    иванов в.п.  Дата создания: 14 сентября 1986 г.
      !
      ! изменен:
      !
      ! 1-001 - оригинал; автор, 14 сентября 1986 г.
      !
      ! 1-002 - обнаружена незначительная ошибка в вычислении
      !
      ! об'ема куба; программист петров, 15 марта 1987 г.
      !
      !-
 
 
 
           2.6.2. Описание процедуры
 
 
           Необходимо поместить в начале каждой процедуры, входя-
 
      щей в модуль, ее описание.
 
           Всегда следует указывать все характеристики  процедуры
 
      независимо от того, есть ли они на  самом  деле.  Например,
 
      если у процедуры  отсутствуют  неявные  входные  параметры,
 
      надо написать следующим образом:
 
      !
      ! неявные входные параметры
      !
      ! отсутствуют
      !
           Описание процедуры включает следующие элементы:
 
           1) функциональное описание  -  указываются  назначение
 
      процедуры и полностью ее интерфейсы. Описание должно содер-
 
      жать основу всех используемых алгоритмов, включая ссылки на
 
      литературные источники там, где это возможно. Следует также
 


                                - 68 -
 
                           00152-01 97 08
 
 
      пояснить, почему выбран  конкретный  алгоритм.  Указываются
 
      характеристики реентерабельности данной процедуры, если они
 
      отличаются от тех характеристик, которые указаны в описании
 
      модуля;
 
           2)  вызывающую  последовательность,   которая   должна
 
      содержать следующее (и в том же порядке):
 
           - код возврата, значение параметра или команду CALL;
 
           - имя процедуры;
 
           - перечень параметров  (обычно  список  регистров  или
 
      параметров).
 
      При программировании  на  Макроассемблере  каждый  параметр
 
      задается символически в виде смещения относительно указате-
 
      ля параметров (AP). Перечислять  параметры  следует  в  том
 
      порядке, в каком они появятся в программе на языке высокого
 
      уровня. При этом необходимо включать характеристики каждого
 
      параметра, используя систему обозначений параметров  проце-
 
      дуры (см. Приложение 2);
 
           3) формальные  параметры  -  перечисляются  все  явные
 
      входные, входные-выходные или выходные параметры. Для  каж-
 
      дого параметра дается  его  небольшое  описание.  Параметры
 
      следует перечислять в том порядке, в каком они  перечислены
 
      в вызывающей последовательности;
 
           4) неявные входные параметры - перечисляются все вход-
 
      ные параметры, хранящиеся внутри или  вне  процедуры  и  не
 
      указанные в перечне параметров. Обычно в данном месте будет
 
      стоять слово "отсутствуют" (см. П. 2.2.2);
 
           5) неявные  выходные  параметры  -  перечисляются  все
 
      выходные параметры, помещаемые вне или внутри  процедуры  и
 
      не указанные в перечне параметров;
 
           6) код завершения или значение  программы  -  перечис-


                                - 69 -
 
                           00152-01 97 08
 
 
      ляются символические имена значений условий,  соответствую-
 
      щие успешному или неудачному  завершению,  которые  возвра-
 
      щаются в виде кода завершения в регистре R0. Если же проце-
 
      дура возвращает  значение  функции,  отличное  от  значения
 
      условия в регистре  R0,  в  описании  приводится  заголовок
 
      "значение программы";
 
           7) побочные эффекты - описываются все возможные побоч-
 
      ные эффекты функционирования, которые не очевидны из  вызы-
 
      вающей последовательности процедуры. Сюда входят  изменения
 
      в распределении памяти, состоянии процесса, операции с фай-
 
      лами и возможные признаки сигналов. Вообще говоря,  следует
 
      документировать все то нестандартное, что процедура  произ-
 
      водит со средой своего функционирования.  Если  в  качестве
 
      побочных эффектов процедура изменяет  содержимое  локальных
 
      или глобальных ячеек памяти, следует это указать в  разделе
 
      неявных выходных параметров.
 
           Пример служит иллюстрацией описания процедуры:
 
      !++
      !
      ! функциональное назначение
      !
      ! возвращает дату и системное время, используя
      !
      ! семантику вызывающей программы в строке символов.
      !
      ! не реентерабельная, использует статическую память.
      !
      ! формальный параметр:
      !
      !   RESULT_ADDR
      !
      ! использование системы МОС ВП: строка символов
      !
      ! тип                         : строка символов
      !
      ! доступ                      : только запись
      !
      ! механизм                    : по дескриптору
      !
      ! адрес дескриптора, в который записываются
      !
      ! дата и системное время


                                - 70 -
 
                           00152-01 97 08
 
 
      !
      ! неявные входные параметры:
      !
      !   отсутствуют
      !
      ! неявные выходные параметры:
      !
      !   отсутствуют
      !
      ! признаки завершения:
      !
      !   SS$_NORMAL   процедура успешно завершила работу
      !
      !   LIB$_STRTRU  успешно, но укорочена исходная строка
      !
      ! побочные эффекты:
      !
      !   запрашивает текущие дату и время у системы МОС ВП
      !
      !--
 
 
           2.7. Планирование сигнализации и обработки условий
 
 
           Существует два способа, посредством которых  процедура
 
      может известить вызвавшую ее программу об успешности своего
 
      завершения. Один способ  заключается  в  возврате  значения
 
      условия в R0. Другой способ состоит в сигнализации  условия
 
      ошибки.
 
           В целях обеспечения более удачного интерфейса с  прог-
 
      раммами пользователей все процедуры  программного  средства
 
      должны либо возвращать значения состояния  (условия),  либо
 
      сигнализировать об условиях ошибки. Вне зависимости от выб-
 
      ранного  способа  следует  в  рамках  данного  программного
 
      средства продумать то, как сделать его более простым с точ-
 
      ки зрения вызова процедур из программ пользователя.
 


                                - 71 -
 
                           00152-01 97 08
 
 
           2.7.1. Основные положения по сигнализации об  условиях
 
      ошибок
 
 
           В ряде случаев сигнализация об условиях ошибки являет-
 
      ся обязательной. Процедуры, которые  в  регистр  R0  выдают
 
      значение функции, не возвращают значение состояния и потому
 
      должны сигнализировать о любой встретившейся ошибке.
 
           Прочие процедуры  могут  пожелать  сигнализировать  об
 
      условиях ошибки в целях повышения своей эффективности. Про-
 
      верка состояния возврата для вызывающей процедуры при  цик-
 
      лических вызовах может занимать время и вредно  сказываться
 
      на производительности вызывающей программы. Например,  если
 
      предполагается, что процедура внутри цикла будет  вызывать-
 
      ся 100 раз, а вероятность сбоя процедуры сравнительно мала,
 
      можно не тратить время на проверку состояния возврата после
 
      каждого вызова в предположении, что  возвращаемое  значение
 
      состояния SS$_NORMAL. Сигнализация об условиях  ошибки  для
 
      такого типа программ оказывается значительно  более  эффек-
 
      тивным средством.
 
           С точки зрения вызывающей программы обработка условия,
 
      о котором выставлен сигнал, является более сложной работой,
 
      чем проверка возвращаемого значения. Более сложной  потому,
 
      что требует написания программы  обработки  исключительного
 
      состояния, которая будет вызываться в случае наличия сигна-
 
      ла об ошибке. Вместе с тем, обработка условий  по  сигналам
 
      позволяет более эффективно работать программе.
 
           Чтобы сигнализировать о наличии условия ошибки, проце-
 
      дура использует  либо  механизм  обработки  исключительного
 
      состояния, обеспечиваемый средствами исходного языка  прог-
 
      раммирования, либо вызывает процедуру  LIB$SIGNAL  исполни-
 


                                - 72 -
 
                           00152-01 97 08
 
 
      тельной библиотеки. При использовании LIB$SIGNAL  процедура
 
      пользователя вызывает LIB$SIGNAL и указывает код условия  и
 
      нуль или ряд параметров, которыми описываются условия выра-
 
      ботки данного кода [1]. В исполнительной библиотеке имеются
 
      также другие процедуры, которые могут оказать помощь в сиг-
 
      нализации и обработки условий [1].
 
 
 
           2.7.2. Основные положения для возвращаемых значений
 
 
           С точки зрения вызывающей программы существенно  проще
 
      проверить возвращаемые значения состояния, чем обрабатывать
 
      условия ошибок, о наличии которых выставляется сигнал. Если
 
      возвращается значение исключительного состояния, в вызываю-
 
      щей программе нет  необходимости  содержать  программу  его
 
      обработки. В вызывающей программе требуется  только  прове-
 
      рить состояние возвращенного значения.
 
           Вместе с тем, в  случае  возврата  значения  состояния
 
      получается меньше  информации  в  вызывающей  программе  об
 
      условиях ошибки, чем в случае выставления сигнала о наличии
 
      условия ошибки. Рекомендуется пользоваться механизмом возв-
 
      рата значений в тех случаях, когда толкование условия ошиб-
 
      ки просто и не требует дополнительных пояснений.  Например,
 
      процедура LIB$GET_VM возвращает значение состояния. Сделано
 
      это потому, что возможные условия состояния не нуждаются  в
 
      дополнительных пояснениях и просты (например,  недостаточно
 
      виртуальной памяти).
 
           Следуя правилам вызова процедур и  обработки  условий,
 
      принятым в МОС ВП, возвращаемая вызывающей программе инфор-
 
      мация должна быть значением состояния (условия) [5].
 


                                - 73 -
 
                           00152-01 97 08
 
 
           2.7.3. Выставление   сигналов   и   возврат   значений
 
      исключительного состояния
 
 
           Пользователю приходится решать, следует ли  выставлять
 
      сигналы о наличии условия ошибки  или  возвращать  значение
 
      состояния в зависимости  от  того  языка  программирования,
 
      который используется для написания процедуры. В ряде языков
 
      высокого уровня крайне сложно написать программу  обработки

      условий, которая должна вызываться в случае появления  сиг-
 
      нала о наличии ошибки.
 
           Независимо от того, какой из  языков  программирования
 
      используется, существуют общие положения относительно того,
 
      когда возвращать значение  состояния,  а  когда  выставлять
 
      сигнал о наличии условия ошибки.
 
           О наличии условия ошибки  следует  выставлять  сигнал,
 
      если:
 
           - процедура возвращает значение  в  регистр  R0  и  не
 
      может возвращать значение условия;
 
           - процедура должна работать быстро и проверки  возвра-
 
      щенного значения условия будут неэффективными;
 
           - процедура будет исполняться многократно (в цикле)  и
 
      поэтому проверка значения условия, которое ей возвращается,
 
      будет сказываться на производительности процедуры;
 
           - та информация, которую желательно передать об  усло-
 
      вии ошибки, не может уместиться в значении условия;
 
           - полезное сообщение об  ошибке  содержит  информацию,
 
      которую нельзя определить до момента выполнения.  Например,
 
      процедура FDL$PARSE должна сообщить  о  том,  какая  строка
 
      файла FDL (язык описания файла)  явилась  причиной  ошибки.
 
      Номер строки, содержащей ошибку, не может быть определен до
 


                                - 74 -
 
                           00152-01 97 08
 
 
      момента  выполнения  процедуры.  Поэтому   предпочтительнее
 
      использовать механизм выставления сигнала, так как информа-
 
      ция о номере строки не может быть возвращена в виде  значе-
 
      ния условия;
 
           - желательно, чтобы выполнялась  конкретная  программа
 
      обработки условий в случае выставления  сигнала  о  наличии
 
      условия ошибки.
 
           Значение условия следует возвращать, если:
 
           - желательно сохранить простым механизм обработки оши-
 
      бок;
 
           - скорость работы механизма проверки наличия ошибок не
 
      играет большой роли;
 
           - общее число возможных ошибок, информация  о  которых
 
      может возвращаться, не велико  и  в  возвращаемом  значении
 
      условия достаточно информации о таких ошибках;
 
           - операции, которые реализуются посредством процедуры,
 
      столь общего характера, что процедура будет  использоваться
 
      на различных уровнях и в различных  условиях  операционного
 
      окружения.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 75 -
 
                           00152-01 97 08
 
 
                            3. Кодирование
 
 
 
           В данном разделе описываются рекомендации по кодирова-
 
      нию модульных процедур. Раздел освещает следующие вопросы:
 
           - основные положения по кодированию;
 
           - инициализация модульных процедур;
 
           - использование средств системного обслуживания систе-
 
      мы МОС ВП;
 
           - вызов необязательных программ пользователя;
 
           - написание реентерабельных по AST программ.
 
 
 
           3.1. Основные положения по кодированию
 
 
           Рассматриваемые  основные  положения  по   кодированию
 
      вытекают из правил модульного  программирования  в  системе
 
      МОС ВП (см. Приложение 1). Среди положений имеются  положе-
 
      ния двух типов: обязательные и рекомендуемые. Для обеспече-
 
      ния модульности программ следует придерживаться тех положе-
 
      ний, которые помечены как обязательные. Так же рекомендует-
 
      ся придерживаться и тех положений, которые изложены в пунк-
 
      тах, помеченных как рекомендуемые. Если придерживаться этих
 
      дополнительных правил, программы пользователя  будут  полу-
 
      чаться логичными и одинаковыми по структуре.
 
 
 
           3.1.1. Написание  позиционно   -   независимого   кода
 
      (обязательное)
 
 
           Модуль считается позиционно-независимым, если он может
 
      правильно выполняться в любом месте виртуальной памяти. При
 
      программировании на языке высокого уровня  системы  МОС  ВП
 
      трудно не запрограммировать в  позиционно-независимом  коде


                                - 76 -
 
                           00152-01 97 08
 
 
      вследствие тех принципов, которые положены в основу  разра-
 
      ботки языков программирования. Вместе с тем, при программи-
 
      ровании  на  языках  Макроассемблер  и  Блисс  в  некоторых
 
      вариантах режимов адресации и адреса операнда (их  комбина-
 
      ции) могут получаться программы, которые не являются  пози-
 
      ционно-независимыми [7].
 
 
 
           3.1.2. Принятые соглашения по наименованиям
 
 
           Следующие  основные   положения   (подпункты   3.1.2.1
 
      - 3.1.2.8) относятся к наименованию средств, процедур, фай-
 
      лов, модулей и программных секций (PSECT). Необходимо  при-
 
      держиваться данных соглашений при выборе имен для  модулей,
 
      программных секций (PSECT) и кодов состояния.  Настоятельно
 
      рекомендуется, чтобы пользователь придерживался также  про-
 
      чих соглашений по наименованиям.
 
 
 
           3.1.2.1. Соглашения    по     наименованию     средств
 
      (рекомендуемые)
 
 
           Чтобы упростить поиск местоположения набора взаимосвя-
 
      занных процедур, рекомендуется сгруппировать такие процеду-
 
      ры в средства. Указание для взаимосвязанных процедур общего
 
      префикса средства - удобный  способ  организации  процедур.
 
      Префикс средства указывается в  первой  части  имени  любой
 
      процедуры, например:
 
           STR$APPEND - STR - это префикс средства  для  процедур
 
      манипулирования с цепочками символов;
 
           BAS$STRIN - BAS - это префикс  средства  для  процедур
 
      поддержки.
 
           Имена средств представляют библиотечные средства. Про-


                                - 77 -
 
                           00152-01 97 08
 
 
      цедура относится к конкретной категории средств  в  зависи-
 
      мости от видов  выполняемых  ею  операций.  Средства  могут
 
      отличаться по соглашениям, используемым ими,  по  обработке
 
      ошибок и приему параметров, а также по основному назначению
 
      средства. В табл. 7 перечислены  некоторые  общие  префиксы
 
      средств.
 
                                                        Таблица 7
 
                     Средства общих библиотек
 
      -----------------------------------------------------------
                 !
      Префикс    !     Содержание
                 !
      -----------------------------------------------------------
                 !
       ADA       ! Процедуры исполнительной библиотеки языка ADA
                 !
       APL       ! Процедуры исполнительной библиотеки языка APL
                 !
       BAS       ! Процедуры исполнительной библиотеки Бейсика
                 !
       B32       ! Процедуры исполнительной библиотеки языка
                 !
                 !Блисс
                 !
       CDU       ! Обслуживающая программа описания команд
                 !
       CLI       ! Интерпретатор командного языка
                 !
       COB       ! Процедуры исполнительной библиотеки языка
                 !
                 !Кобол
                 !
       COR       ! Процедуры исполнительной библиотеки языка
                 !
                 !Корал
                 !
       C74       ! Процедуры исполнительной библиотеки
                 !
                 !языка Кобол-74
                 !
       DBG       ! Отладчик
                 !
       DBL       ! Процедуры исполнительной библиотеки
                 !
                 !языка дибол
                 !
       ERF       ! Форматер регистратора ошибок
                 !
       FDV       ! Процедуры библиотеки драйвера форм
                 !  
                 !системы СУД


                                - 78 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 7
      -----------------------------------------------------------
                 !
      Префикс    !     Содержание
                 !
      -----------------------------------------------------------
                 !
       FOR       ! Процедуры исполнительной библиотеки Фортрана
                 !
       LBR       ! Процедуры обслуживающей программы-библиотекаря
                 !
       LIB       ! Процедуры общего назначения исполнительной
                 !
                 !библиотеки
                 !
       MTH       ! Математические процедуры исполнительной
                 !
                 !библиотеки
                 !
       OTS       ! Независимые от языка программирования
                 !
                 !процедуры исполнительной библиотеки
                 !
       PAS       ! Процедуры исполнительной библиотеки языка
                 !
                 !Паскаль
                 !
       PLI       ! Процедуры исполнительной библиотеки
                 !
                 !языка ПЛ/1
                 !
       RMS       ! СУД-32
                 !
       SMG       ! Рроцедуры обслуживания экрана исполнительной
                 !
                 !библиотеки
                 !
       SOR       ! Процедуры обслуживающей программы сортировки
                 !
       STR       ! Процедуры манипулирования с строками
                 !
                 !исполнительной библиотеки
                 !
       М32       ! Эмуляция архитектуры системы МОС ВП
 
           Можно создать собственные  средства,  задав  отдельное
 
      имя и номер средства. Имя средства должно быть единственным
 
      и содержать  от  1  до  27  символов.  Рекомендуется  имена
 
      средств выбирать состоящими из 2-4 символов. Все поставляе-
 
      мые средства МОС ВП содержат после префикса  денежный  знак
 
      ($). В задаваемых пользователями именах средств должен при-
 
      сутствовать символ подчеркивания (_), а  не  денежный  знак
 


                                - 79 -
 
                           00152-01 97 08
 
 
      ($) во избежание возможных совпадений имен.
 
           Номер средства  используется  в  определении  значений
 
      исключительных состояний. Бит 27 (STS$V_CUST_DEF)  значения
 
      условия указывает, является ли данное средство поставляемым
 
      или же создано пользователем.  Данный  разряд  должен  быть
 
      равен 1, если номер средства создан пользователем. Для соз-
 
      дания  значения  условия  и  соответствующего  ему   текста
 
      используется обслуживающая программа выдачи сообщений [8].
 
 
 
           3.1.2.2. Соглашения    по    наименованию     процедур
 
      (рекомендуемые)
 
 
           При создании процедуры ее имя делается глобальным, чем
 
      обеспечивается возможность другим процедурам в том же обра-
 
      зе вызывать данную процедуру. Примерами процедур с глобаль-
 
      ными именами могут служить процедуры  общей  исполнительной
 
      библиотеки. В таких условиях требуется соблюдать соглашение
 
      по наименованию в целях предотвращения совпадения имен гло-
 
      бальных процедур в одном и том же образе.
 
           Правила наименования точек входа процедур имеют  общий
 
      вид:
 
      средство$имя - для поставляемых процедур;
 
      средство_имя - для процедур пользователя;
 
      средство - это имя средства из 2-4 символов;
 
      имя - это идентификатор из 1-27 символов.
 
           Полное имя процедуры не может содержать более 31  сим-
 
      вола.
 
           Имя средства и наименование идентификатора разделяются
 
      денежным знаком ($), если процедура поставляемая, и  симво-
 
      лом подчеркивания (_), если процедура разработана пользова-
 


                               - 80 -
 
                           00152-01 97 08
 
 
      телем. Такое соглашение позволяет избежать совпадения  имен
 
      процедур, разработанных поставщиком и пользователями.
 
           Имя процедуры обычно состоит из глагола и  дополнения.
 
      Вместе глагол и дополнение описывают выполняемую процедурой
 
      работу.  Например,  процедура  исполнительной   библиотеки,
 
      которая предназначена  для  выделения  виртуальной  памяти,
 
      называется LIB$GET_VM.
 
           Ряд процедур не  предназначен  для  вызова  извне  тех
 
      средств, внутри которых они находятся. Такие процедуры дос-
 
      тупны только посредством внутренних вызовов из набора  про-
 
      цедур  и  не  реализуют  сами  каких-либо  функций  данного
 
      средства. В именах таких процедур содержится  два  денежных
 
      знака ($$), если они поставляемые, либо три символа подчер-
 
      кивания (_), если они разработаны пользователем. (три  сим-
 
      вола подчеркивания необходимы для того, чтобы избежать сов-
 
      падения с определенными пользователем идентификаторами зна-
 
      чений исключительных состояний, в которых используется  два
 
      символа подчеркивания).
 
           Примеры:
 
           1. LIB$GET_VM - поставляемая глобальная процедура.
 
           2. LIB_PRINT_REPORT - глобальная  процедура,  разрабо-
 
      танная пользователем.
 
           3. OTS$$INTERNAL - поставляемая внутренняя процедура.
 
           4. LIB_ADD_TAX - внутренняя  процедура,  разработанная
 
      пользователем.
 


                                - 81 -
 
                           00152-01 97 08
 
 
           3.1.2.3. Соглашения     по     наименованию     файлов
 
      (рекомендуемые)
 
 
           Следует получать имя файла из имени  (имен)  процедуры
 
      (процедур), содержащейся в модуле,  который  содержит  этот
 
      файл.
 
           Если модуль содержит одну процедуру, имя файла состоит
 
      из имени процедуры. При желании  можно  исключить  денежные
 
      знаки ($) и символы подчеркивания (_), но в этом нет  необ-
 
      ходимости. Тип файла  -  это  стандартный  используемый  по
 
      умолчанию тип файла, принятый в языке программирования,  на
 
      котором написан модуль. Например, файл, содержащий процеду-
 
      ру MTH$EXP, называется MTHEXP.MAR. По  этому  имени  видно,
 
      что файл MTHEXP.MAR содержит процедуру MTH$EXP и что проце-
 
      дура написана на Макроассемблере СМ 1700.
 
           Иногда модуль, образующий файл, может содержать  более
 
      одной   процедуры.   Например,   процедуры   LIB$GET_VM   и
 
      LIB$FREE_VM исполнительной библиотеки  содержатся  в  одном
 
      модуле и, следовательно, в  одном  файле.  В  таком  случае
 
      используется в качестве имени файла более общее имя.  Такое
 
      имя слагается из префикса средства и  первых  существитель-
 
      ных, которые являются общими для всех имен процедур, содер-
 
      жащихся в модуле (в данном случае - VM). Таким образом, имя
 
      файла,  содержащего  процедуры  LIB$GET_VM  и  LIB$FREE_VM,
 
      будет LIBVM.B32 (тип файла B32 указывает, что модуль  напи-
 
      сан на языке Блисс системы МОС ВП).
 


                                - 82 -
 
                           00152-01 97 08
 
 
           3.1.2.4. Соглашения    по     наименованию     модулей
 
      (обязательные)
 
 
           Имена модулей идентичны именам файлов за тем лишь иск-
 
      лючением, что в именах модулей  отсутствуют  расширения,  а
 
      денежный знак ($) или символ  подчеркивания  (_),  которыми
 
      разделяются префикс средства и имя идентификатора, не  уда-
 
      лены.
 
           Например,  процедура  MTH$EXP  содержится   в   модуле
 
      MTH$EXP  и  файле  MTHEXP.MAR.   Процедуры   LIB$GET_VM   и
 
      LIB$FREE_VM содержатся в модуле LIB$VM и файле LIBVM.B32.
 
 
 
           3.1.2.5. Соглашения по наименованию программных секций
 
      (PSECT) (обязательные)
 
 
           Секции программы и секции данных библиотечной процеду-
 
      ры пользователя представляют  две  независимые  программные
 
      секции (PSECT), которые именуются соответственно  _FAC_CODE
 
      и _FAC_DATA, где FAC - наименование средства.  Поставляемые
 
      программные  секции  в  качестве  имен  программных  секций
 
      (PSECT) использует соответственно _FAC$CODE и _FAC$DATA.
 
           Позиционно-независимая постоянная (неизменная)  инфор-
 
      мация находится  в  программной  секции  (PSECT)  с  именем
 
      _FAC_CODE (_FAC$CODE для  поставляемых  процедур)  в  целях
 
      сокращения   размеров   ссылок.   Например,   _LIB$CODE   и
 
     ых секций (PSECT), которые используются процедурами LIB$.
 
           Шаблон на ведущие символы  подчеркивания  используется
 
      компоновщиком для  того,  чтобы  распознавать  библиотечные
 
      процедуры и разместить их в выполняемом образе за пользова-
 
      тельской  программой.  Тем  самым  исключается  возможность
 
      помещения библиотечной процедуры между двумя модулями поль-


                                - 83 -
 
                           00152-01 97 08
 
 
      зователя и вероятность порчи любого байта или  слова  прог-
 
      раммы пользователя.
 
           Не во всех языках программирования системы МОС ВП пре-
 
      доставляется контроль имен программных секций (PSECT). Так,
 
      в Бейсике и Паскале нельзя контролировать имена программных
 
      секций (PSECT), если только не использовать COMMON. Исполь-
 
      зование COMMON нарушает правила  модульного  программирова-
 
      ния.
 
 
 
           3.1.2.6. Соглашения  по  наименованию   блокированного
 
      ресурса (рекомендуемые)
 
 
           При использовании средства управления захватом (блоки-
 
      рованием) системы МОС ВП имена ресурсов блокировок на уров-
 
      не корня (захват без "предка") должны выводиться  из  имени
 
      средства. Используемое соглашение по наименованию таково:
 
           Средство$имя - имя ресурса для поставляемых процедур;
 
           Средство_имя - имя ресурсов  для  процедур,  созданных
 
      пользователем.
 
           Следование данному соглашению предотвратит возникнове-
 
      ние непреднамеренных конфликтных ситуаций с ресурсами.
 
 
 
           3.1.2.7. Соглашения   по    наименованию    глобальной
 
      переменной (рекомендуемые)
 
 
           Глобальные  переменные  следует  именовать,  используя
 
      формат:
 
           Средство$GT_имяпеременной - имя глобальной  переменной
 
      для поставляемых процедур;
 
           Средство_GT_имяпеременной - имя глобальной  переменной
 
      для процедур, созданных пользователем.


                                - 84 -
 
                           00152-01 97 08
 
 
           Буква "T" (после G) служит для указания содержимого  и
 
      применения глобальной переменной. Возможные значения T при-
 
      ведены в табл. 8.
 
                                                        Таблица 8
 
            Код содержимого и применения глобальной переменной
 
      -----------------------------------------------------------
              !
      Значение!  Содержание и использование глобальной переменной
              !
          т   !
              !
      -----------------------------------------------------------
              !
          A   !  Адрес
              !
          B   !  Целое байтовое
              !
          C   !  Одиночный символ
              !
          D   !  Число с плавающей запятой формата D
              !
          E   !  Зарезервировано (разработчиком)
              !
          F   !  Число с плавающей запятой формата F
              !
          G   !  Число с плавающей запятой формата G
              !
          H   !  Число с плавающей запятой формата H
              !
          I   !  Зарезервировано под расширения целых чисел
              !
          J   !  Зарезервировано для пользователей под расширения
              !
              !для других кодов
              !
          K   !  Константа
              !
          L   !  Целое длинное слово
              !
          M   !  Маска поля
              !
          N   !  Цепочка цифровых символов (все символы - байты)
              !
          O   !  Октаслово
              !
          P   !  Упакованная строка
              !
          Q   !  Целое квадрослово
              !
          R   !  Записи (структура)
              !
          S   !  Размер поля
              !
          T   !  Цепочка текстовой (символьной) информации


                                - 85 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 8
      -----------------------------------------------------------
              !
      Значение!  Содержание и использование глобальной переменной
              !
          т   !
              !
      -----------------------------------------------------------
              !
          U   !  Наименьшая адресуемая единица памяти
              !
          V   !  Битовое поле
              !
          W   !  Целое слово
              !
          X   !  Зависит от контекста (общее)
              !
          Y   !  Зависит от контекста (общее)
              !
          Z   !  Не задано или нестандартное
 
           Аналогично формат адресуемых глобальных массивов имеет
 
      вид:
 
           Средство$AT_имяпеременной - имя глобальной  переменной
 
      для поставляемых процедур;
 
           Средство_AT_имяпеременной - имя глобальной  переменной
 
      для процедур, созданных пользователем.
 
           И вновь буква "T" служит для указания содержимого и
 
      использования   адресуемого    глобального    массива  (см.
 
      Табл. 8).
 
 
 
           3.1.2.8. Соглашения по наименованию кода  состояния  и
 
      значения исключительного состояния (обязательные)
 
 
           Формат кодов состояния и значений исключительного сос-
 
      тояния следующий:
 
           Средство$_состояние - код или значение  состояния  для
 
      поставляемых процедур;
 
           Средство_состояние - код или  значение  состояния  для
 
      процедур, созданных пользователем.
 


                                - 86 -
 
                           00152-01 97 08
 
 
           3.1.3. Использование     общих     исходных     файлов
 
      (рекомендуемые)
 
 
           В некоторых программах  пользователя  может  оказаться
 
      необходимым в нескольких модулях делать идентичные описания
 
      параметров. В языках программирования системы МОС ВП  можно
 
      сосредоточить такие описания в одном месте, используя общие
 
      исходные файлы. В табл. 9 приведены описания общих исходных
 
      файлов для языков программирования системы МОС ВП.
 
                                                        Таблица 9
 
                  Описание общих исходных файлов
 
      -----------------------------------------------------------
                    !
      Язык програм- ! Описание общего файла исходных текстов
                    !
      мирования     !
                    !
      -----------------------------------------------------------
                    !
      АДА           !  Чтобы совместно использовать Oбщие описа-
                    !
                    !ния в программах  на  языке АДА, необходимо
                    !
                    !включить  описания  в  блок (как  отдельную
                    !
                    !компилируемую единицу) и  обеспечить  обзор
                    !
                    !этого блока, используя оператор WITH в  тех
                    !
                    !программах, в  которых  желательно  исполь-
                    !
                    !зовать общие описания
                    !
      Бэйсик        !  Можно использовать в  программе директиву
                    !
                    !%INCLUDE   Бейсика  для  включения   общего
                    !
                    !исходного  файла либо  запись CDD
                    !
      Блисс         !  В исходном тексте программы  может содер-
                    !
                    !жаться  выбор  списка REQUIRE  или LIBRARY,
                    !
                    !который указывает файл для включения в нуж-
                    !
                    !ное место описания
                    !
      Кобол         !  оператор  COPY задает  ту запись, которая
                    !


                                - 87 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 9
      -----------------------------------------------------------
                    !
      Язык програм- ! Описание общего файла исходных текстов
                    !
      мирования     !
                    !
      -----------------------------------------------------------
                    !копируется  из  библиотечного файла Кобола,
                    !
                    !библиотечного  файла  системы МОС ВП или из
                    !
                    !каталога  общих  данных  (CDD) и помещается
                    !
                    !в исходный текст программы
                    !
      Фортран       !  Оператором INCLUDE задается файл или биб-
                    !
                    !лиотечный модуль, который должен быть вклю-
                    !
                    !чен  в  текст  программы в месте применения
                    !
                    !данного оператора. Можно также использовать
                    !
                    !запись CDD
                    !
      Макроассемблер!  Вспомогательный  исходный  файл либо биб-
                    !
                    !лиотеку Макроопределений можно задать в ко-
                    !
                    !мандной строке либо воспользоваться записью
                    !
                    !CDD
                    !
      Паскаль       !  Директива %INCLUDE и атрибут  INHERIT за-
                    !
                    !дают те файлы, которые должны  включаться в
                    !
                    !указатель  описания. Можно  также использо-
                    !
                    !вать запись CDD
                    !
      ПЛ/1          !  Оператор  препроцессора  %INCLUDE  задает
                    !
                    !файл, который следует поместить в исходный.
                    !
                    !можно также использовать запись CDD


                                - 88 -
 
                           00152-01 97 08
 
 
           3.1.4. Обеспечение удобочитаемости программ
 
 
           При кодировании новой прикладной  программы  важно  не
 
      забывать о том, что в недалеком будущем кому-то,  возможно,
 
      придется вносить в программу изменения. Чтобы  такие  неиз-
 
      бежные изменения было  проще  вносить,  необходимо  сделать
 
      свою программу простой и понятной, легко читаемой.
 
           Следующие  основные  положения  помогут  в  разработке
 
      программ, которые легко читаются и воспринимаются:
 
           - следует использовать идентификаторы вместо чисел;
 
           - применять заглавные и строчные буквы;
 
           - добавлять необязательные пробелы;
 
           - вставлять блоки комментариев.
 
 
 
           3.1.4.1. Использование символьных  обозначений  вместо
 
      чисел (рекомендуется)
 
 
           В  тексте  программ  следует  использовать  символьные
 
      обозначения (идентификаторы), а не числа. Поскольку иденти-
 
      фикаторы представляют мнемонические обозначения,  программы
 
      становятся более ясными и  обеспечивают  больше  информации
 
      для таблиц перекрестных ссылок. Всегда рекомендуется приме-
 
      нять идентификатор для константы, которая  будет  использо-
 
      вать несколько раз. Если значение такого  идентификатора  в
 
      будущем может измениться, потребуется только изменить  зна-
 
      чение в месте его задания, а не всюду в программе, где  оно
 
      используется.  Следовательно,  применение   идентификаторов
 
      вместо чисел  позволяет  проще  осуществлять  сопровождение
 
      процедур. Более того, по  идентификатору  проще  проследить
 
      все места в программе, где  содержаться  ссылки  на  данный
 
      идентификатор. В таблице перекрестных  ссылок  для  данного


                                - 89 -
 
                           00152-01 97 08
 
 
      идентификатора будут указаны все места программы, где  есть
 
      ссылки на идентификатор.
 
           Пример иллюстрирует информацию, которую можно получить
 
      об идентификаторе по таблице перекрестных ссылок (иллюстри-
 
      руется содержимое файла LIGHT.LIS, который создан посредст-
 
      вом команды $ PASCAL/LIS/CROSS LIGHT.PAS):
 
      MAX_SPEED
 
      01                     исходный текст программы;
 
      0001          PROGRAM MAX_SPEED;
 
      0002 (+)
 
      0003 (данной программой иллюстрируется использование
 
      0004 (идентификатора вместо числа для улучшения
 
      0005 (обозримости программы.
 
      0006 (в программе описывается идентификатор для скорости
 
      0007 (света, а затем используется идентификатор для вычи-
 
      0008 (сления скорости звездного корабля "леденец" и ко-
 
      0009 (рабля "злодеев".
 
      0010
 
      0011          CONST
 
      0012             SPEED_OF_LIGHT = 3*(10**8);
 
      0013
 
      0014          VAR
 
      0015             LOLLIPOP_SPEED : INTEGER;
 
      0016             VILLAIN_SPEED    : INTEGER;
      
      0017
 
      0018           BEGIN
 
      0019             LOLLIPOP_SPEED:= 8 * SPEED_OF_LIGHT;
 
      0020             VILLAIN_SPEED: = 4 * SPEED_OF_LIGHT;
 
      0021           END
 
      0022


                                - 90 -
 
                           00152-01 97 08
 
 
      MAX_SPEED
 
      01                таблица перекрестных ссылок
 
      LOLLIPOP_SPEED   VAR INTEGER (IN PROGRAM MAX_SPEED)
 
                             15      19 =
 
      INTEGER          TYPE
 
                             *       15       16
 
      VILLAIN_SPEED    VAR INTEGER (IN PROGRAM MAX_SPEED)
 
                             16      20 =
 
      MAX_SPEED        PROG [PSECT($CODE)]
 
      SPEED_OF_LIGHT   CONST 300000000(IN PROGRAM MAX_SPEED)
 
                             12      19       20
 
           В таблице перекрестных ссылок указываются места описа-
 
      ния (об'явления) идентификаторов и места, в которых на  них
 
      имеются ссылки.
 
 
 
           3.1.4.2. Использование  знаков  верхнего   и   нижнего
 
      регистров (рекомендуется)
 
 
           В исходных текстах, за исключением комментариев,  сле-
 
      дует пользоваться заглавными буквами латинского алфавита. В
 
      комментариях можно использовать  и  заглавные,  и  строчные
 
      буквы нижнего и верхнего  регистров.  Комментарии,  которые
 
      представляют законченные предложения, должны  начинаться  с
 
      заглавной буквы и заканчиваться точкой.
 
           Все исходные тексты программ должны быть  закодированы
 
      с помощью заглавных букв латинского  алфавита,  если  жела-
 
      тельно, чтобы они не зависели от операционной системы. Хотя
 
      система МОС ВП и реализации ее языков  программирования  не
 
      чувствительны к использованию  заглавных  и  строчных  букв
 
      нижнего и верхнего регистров, прочие операционные системы и
 


                                - 91 -
 
                           00152-01 97 08
 
 
      реализации языков программирования  чувствительны  к  тому,
 
      какие буквы используются. (язык си системы МОС ВП  является
 
      исключением: язык си чувствителен к используемым символам).
 
      Прикладные программы, которые закодированы с использованием
 
      смеси заглавных и строчных  букв,  возможно,  нельзя  будет
 
      просто перенести в другие системы.
 
 
 
           3.1.4.3. Добавление      необязательных       пробелов
 
      (рекомендуется)
 
 
           За запятой должен следовать один пробел. Пробел должен
 
      также предшествовать и следовать за знаком  равенства  (=).
 
      Один пробел должен предшествовать  левой  круглой  (()  или
 
      левой квадратной скобке ([) (за исключением  Макроассембле-
 
      ра), но не левой угловой скобке (<).  Пробел  также  должен
 
      следовать за восклицательным знаком (!) или точкой с  запя-
 
      той (;) для  отделения  комментариев  от  исходного  текста
 
      программы. Арифметические операторы (знаки операций  "плюс"
 
      (+) и "минус" (-)) в выражениях должны быть окружены пробе-
 
      лами.
 
           Программа на Бейсике в следующем примере  иллюстрирует
 
      правильное использование необязательных пробелов:
 
      10 !+
         !
         ! в программе на Бейсике преобразуется строка
         !
         ! символов, представляющая шестнадцатеричное
         !
         ! значение, в длинное слово, после чего к результату
         !
         ! прибавляется единица.
         !
         ! об'явление использованной внешней подпрограммы.
         !
         !-
 
         EXTERNAL LONG FUNCTION OTS$CVT_TZ_L
 


                                - 92 -
 
                           00152-01 97 08
 
 
         !+
 
         ! выполнение преобразования.
 
         !-
 
         HEXVAL$ = "80012BFA"
 
         RET_STAT% = OTS$CVT_TZ_L (HEXVAL$, HEX%)
 
         !+
 
         ! добавление единицы к результату.
 
         !-
 
         HEX% = HEX% + 1
 
         END
 
 
           3.1.4.4. Вставка блока комментариев (рекомендуется)
 
 
           Прокомментировать блок операторов можно, написав  одну
 
      либо несколько строк, предшествующих блоку. В первой строке
 
      комментария находится один символ "плюс" (+),  в  последней
 
      один символ "минус" (-).  Блок  комментариев  не  требуется
 
      отделять дополнительными пустыми строками; две строки  фла-
 
      гов,  начинающиеся   символом   "плюс"   (+)   и   символом
 
     ожет все же потребоваться в блок комментариев включить  пус-
 
      тые строки для улучшения читаемости. Разделители, указываю-
 
      щие наличие комментария, отделяются от  текста  комментария
 
      одним пробелом; исключение составляют первая строка с  пер-
 
      вым  знаком  "плюс"  (+)  и  последняя  строка  со   знаком
 
      "минус" (-), что иллюстрирует пример:
 
      !+
      !
      !   данная программа иллюстрирует вызов процедуры
      !
      !   STR$PREFIX из библиотеки исполнительных процедур
      !
      !   инициализация используемых строк символов
      !
      !-
 
          A$ = "ABC"


                                - 93 -
 
                           00152-01 97 08
 
 
 
          B$ = "DEF"
 
      !+
      !
      !   вызов STR$PREFIX
      !
      !-
 
          ISTAT = STR$PREFIX (A$, B$)
 
          END
 
 
           3.1.5. Использование средств  системного  обслуживания
 
      системы МОС ВП
 
 
           Не все средства системного обслуживания системы МОС ВП
 
      являются модульными в смысле определений  настоящего  доку-
 
      мента. Процедуры, которые  вызывают  немодульные  системные
 
      программы обслуживания, сами  являются  немодульными.  Если
 
      процедура использует немодульную системную программу обслу-
 
      живания, следует указать такую программу в разделе  "побоч-
 
      ные эффекты" описания процедуры (п. 2.5.2).
 
 
 
           3.1.6. Вызов необязательных пользовательских  программ
 
      развязки
 
 
           Необязательная  пользовательская  программа   развязки
 
      представляет удобный способ передачи управления  вызывающей
 
      программе в критической точке алгоритма, реализуемого  про-
 
      цедурой. Наиболее общие программы развязки связаны с  обра-
 
      боткой успешности завершения работы или обработкой  ошибок.
 
      Управление будет передано из процедуры  пользователя  подп-
 
      рограмме обработки ошибок, если указанная ошибка  обнаружи-
 
      лась внутри процедуры. Для передачи  управления  вызывающая
 
      программа должна передать вызываемой процедуре  в  качестве
 
      параметра программу  развязки.  Для  того  чтобы  облегчить


                                - 94 -
 
                           00152-01 97 08
 
 
      вызывающей программе передачу информации программе  развяз-
 
      ки, процедура должна использовать  необязательный  параметр
 
      USER-ARG, который вызывающая программа может передать своей
 
      программе развязки. Процедура просто копирует элемент спис-
 
      ка параметров, соответствующий параметру программы  развяз-
 
      ки, если такая существует, в перечень  параметров,  который
 
      она передает программе развязки. Этим обеспечивается тот же
 
      эффект, что и поуровневая адресация.
 
           Существует два типа данных в системе МОС  ВП,  которые
 
      можно использовать для передачи в качестве параметра  прог-
 
      рамме развязки:
 
           1) маска точки входа процедуры;
 
           2) связанное с процедурой значение.
 
           Для обеспечения интерфейса процедуры  с  подпрограммой
 
      развязки следует прежде всего решить,  какого  типа  данные
 
      использовать: маску точки входа процедуры или  связанное  с
 
      процедурой значение. Содержимое списка параметров для прог-
 
      раммы развязки будет  отличаться  в  зависимости  от  того,
 
      какой тип данных укажет пользователь.
 
 
 
           3.1.6.1. Маска точки входа процедуры
 
 
           Маска точки входа процедуры (DSC$K_DTYPE_ZEM)  исполь-
 
      зуется в Фортране и большинстве других языков  программиро-
 
      вания, а так же процедурами исполнительной библиотеки, сис-
 
      темой управления данными и средствами системного обслужива-
 
      ния.
 
           В случае передачи маски  точки  входа  процедуры  пос-
 
      редством ссылки точка  входа  перечня  параметров  содержит
 
      адрес подлежащей вызову  маски  точки  входа  процедуры.  В
 


                                - 95 -
 
                           00152-01 97 08
 
 
      целях обеспечения возможности работы программы  развязки  с
 
      использованием маски точки  входа  процедура  должна  иметь
 
      следующую вызывающую последовательность:
 
           CALL процедура [программа_развязки[,аргумент]]
 
           В данном примере  параметр  программа_развязки  -  это
 
      функциональный вызов  типа  маски  точки  входа  процедуры,
 
      который передается посредством ссылки, а параметр  аргумент
 
      не задан.
 
 
 
           3.1.6.2. Связанное с процедурой значение
 
 
           Связанное  с  процедурой  значение   (DSC$K_DTYPE_BPV)
 
      используется в Паскале и других языках  программирования  в
 
      тех случаях, когда должен быть известен контекст процедуры.
 
      Процедура могла выполнить адресацию верхнего  уровня  пере-
 
      менной, описанной синтаксически во внешнем блоке и,  следо-
 
      вательно, размещенной  в  ином  фрагменте  программы  (если
 
      используется маска точки входа  процедуры,  такой  контекст
 
      задается в параметре USER-ARG).
 
           В случае связанного с процедурой значения,  передавае-
 
      мого по ссылке,  точка  входа  списка  параметров  содержит
 
      адрес двух длинных  слов.  Первое  длинное  слово  содержит
 
      адрес процедуры, а второе длинное слово - указатель  среды,
 
      который следует загрузить в регистр R1 перед вызовом проце-
 
      дуры.  Такой  указатель  среды  позволяет  задать  контекст
 
      действующей программы пользователя с тем, чтобы можно  было
 
      выполнить адресацию верхнего уровня. Для того чтобы обеспе-
 
      чить вызов программы развязки с помощью связанного с проце-
 
      дурой значения, передаваемого посредством ссылки,  вызываю-
 
      щая последовательность должна быть такова:
 


                                - 96 -
 
                           00152-01 97 08
 
 
          CALL процедура [программа_развязки[,аргумент]]
 
           В данном примере программа_развязки  -  функциональный
 
      вызов типа связанного с процедурой значения, которое  пере-
 
      дается посредством ссылки, а параметр аргумент не задан.
 
           Если желательно использовать данные типа  связанное  с
 
      процедурой значение для передачи доступа к пользовательской
 
      программе, заданной в виде  маски  точки  входа  процедуры,
 
      следует передать первое длинное слово посредством  значения
 
      и опустить второе длинное слово. Тогда  программа  развязки
 
      будет иметь следующую вызывающую последовательность:
 
           Состояние = программа_развязки(...[,аргумент])
 
           В данном примере состояние -  длинное  слово  значения
 
      состояния, которое передается посредством значения, а пара-
 
      метр аргумент не задан. Процедура пользователя копирует  32
 
      разрядную точку входа списка параметров,  переданную  вызы-
 
      вающей программой в список параметров для программы развяз-
 
      ки. Таким образом, вызывающая программа и ее программа раз-
 
      вязки могут обмениваться информацией, используя любые  типы
 
      данных, типы доступа, механизмы передачи параметров.
 
 
 
           3.2. Инициализация модульных процедур
 
 
           Некоторые модульные процедуры должны самоинициализиро-
 
      ваться, прежде чем они могут  правильно  работать.  Примеры
 
      инициализации:
 
           - хранение значения в статической памяти, причем  зна-
 
      чение может быть определено только  в  процессе  выполнения
 
      программы;
 
           - об'явление использования программы обработки  выхода
 
      с помощью средства системного обслуживания $DCLEXH;
 


                                - 97 -
 
                           00152-01 97 08
 
 
           - выделение ресурса один раз в рамках процесса;
 
           - открытие файла при первом вызове процедуры.
 
           Инициализацию следует производить аккуратно с сохране-
 
      нием модульности.
 
           Инициализация не должна влиять на вызывающую  програм-
 
      му.  Поэтому  следует  избегать  инициализации  посредством
 
      задания точки входа, к которой нужно  обратиться  до  того,
          
      как будет обращение к любой иной  точке  входа.  Назначение
 
      точки входа, к которой следует обратиться  сначала,  вынуж-
 
      дает вызывающую программу передавать точку входа  инициали-
 
      зации той программе, которая ее вызывала, и так далее. Пот-
 
      ребуется также переписывать вызывающие программы, если воз-
 
      никнет необходимость заменить процедуру с вызовом инициали-
 
      зации на процедуру, в которой такого вызова не было.
 
           Если в процедуре используется LIB$INITIALIZE,  следует
 
      сохранить модульную среду, которая бы не противоречила сре-
 
      де,   созданной    другими    процедурами,    используемыми
 
      LIB$INITIALIZE [1].
 
           Существует несколько способов инициализации процедур:
 
           - инициализация на этапе компиляции или компоновки;
 
           - использование      механизма,       предоставляемого
 
      LIB$INITIALIZE, для выполнения инициализации один  раз  при
 
      каждой активизации образа;
 
           - установка флага первого входа при запуске;
 
           - инициализация памяти всякий раз, когда она распреде-
 
      ляется на этапе прогона.
      
           В табл. 10 приводится обзор этих способов.
 


                                - 98 -
 
                           00152-01 97 08
 
 
                                                       Таблица 10
 
                           Способы инициализации
 
      -----------------------------------------------------------
               !
      Требуемая!                Способ
               !
      инициали-!-------------------------------------------------
               !         !         !         !         !
      зация    !Инициали-!Вызов    !Установка!Инициали-!Инициали-
               !зация на !LIB$INI- !флага    !зация    !зация
               !этапе    !TIALIZE  !первого  !каждый   !при каж-
               !компиля- !перед го-!входа (на!раз,когда!дом вызо-
               !ции/ком- !ловной   !этапе    !память   !ве проце-
               !поновки  !програм- !прогона) !выделяет-!дуры (на
               !         !мой (на  !         !ся (на   !этапе
               !         !этапе    !         !этапе    !прогона)
               !         !прогона) !         !прогона) !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Статичес-!    +    !    +    !    +    !         !
               !         !         !         !         !
      кой памя-!         !         !         !         !
               !         !         !         !         !
      ти       !         !         !         !         !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Стековой !         !         !         !         !  +
               !         !         !         !         !
      памяти   !         !         !         !         !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      массовой !         !         !         !    +    !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Для выде-!         !         !         !         !
               !         !         !         !         !
      ления ре-!         !    +    !    +    !         !
               !         !         !         !         !
      сурсов   !         !         !         !         !
               !         !         !         !         !
      (распре- !         !         !         !         !
               !         !         !         !         !
      деления) !         !         !         !         !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Для уста-!         !         !         !         !
               !         !         !         !         !
      новки    !         !         !         !         !
               !         !         !         !         !
      программы!         !    +    !    +    !         !
               !         !         !         !         !
      обработки!         !         !         !         !


                                - 99 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 10
      -----------------------------------------------------------
               !
      Требуемая!                Способ
               !
      инициали-!-------------------------------------------------
               !         !         !         !         !
      зация    !Инициали-!Вызов    !Установка!Инициали-!Инициали-
               !зация на !LIB$INI- !флага    !зация    !зация
               !этапе    !TIALIZE  !первого  !каждый   !при каж-
               !компиля- !перед го-!входа (на!раз,когда!дом вызо-
               !ции/ком- !ловной   !этапе    !память   !ве проце-
               !поновки  !програм- !прогона) !выделяет-!дуры (на
               !         !мой (на  !         !ся (на   !этапе
               !         !этапе    !         !этапе    !прогона)
               !         !прогона) !         !прогона) !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Выхода   !         !         !         !         !
               !         !         !         !         !
      $EXIT    !         !         !         !         !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Для того,!         !         !         !         !
               !         !         !         !         !
      чтобы от-!         !         !         !         !
               !         !         !         !         !
      крыть по-!         !    +    !    +    !         !
               !         !         !         !         !
      стоянный !         !         !         !         !
               !         !         !         !         !
      файл про-!         !         !         !         !
               !         !         !         !         !
      цесса    !         !         !         !         !
               !         !         !         !         !
      -----------------------------------------------------------
               !         !         !         !         !
      Для уста-!         !         !         !         !
               !         !         !         !         !
      новки    !         !         !         !         !
               !         !         !         !         !
      программы!         !         !         !         !
               !         !         !         !         !
      обработки!         !    +    !         !         !
               !         !         !         !         !
      перед ос-!         !         !         !         !
               !         !         !         !         !
      новной   !         !         !         !         !
               !         !         !         !         !
      програм- !         !         !         !         !
               !         !         !         !         !
      мой      !         !         !         !         !
               !         !         !         !         !


                                - 100 -
 
                           00152-01 97 08
 
 
           3.2.1. Инициализация памяти
 
 
           Для процедуры, которая порождает предсказуемые резуль-
 
      таты, все статически и динамически  распределяемые  области
 
      памяти должны быть проинициализированы известными значения-
 
      ми перед тем, как из них будет считываться информация. Ини-
 
      циализация динамически  распределяемых  данных  стековой  и
 
      массовой памяти связана с необходимостью записать  информа-
 
      цию при каждом выделении места для нее и перед ее  считыва-
 
      нием.
 
           Если у процедуры имеется  статическая  память,  обычно
 
      она инициализируется нулями. В некоторых языках  программи-
 
      рования, например, в языке Блисс, не требуется явно  произ-
 
      водить инициализацию статической  памяти.  В  таких  языках
 
      автоматически производится инициализация статической  памя-
 
      ти - заполнение ее нулями.
 
           Существует три способа явной инициализации памяти:
 
           1) можно использовать оператор инициализации;
 
           2) проверять и устанавливать флаг  первого  входа  при
 
      запуске программы (см. Подпункт 3.3.4.2);
 
           3) использовать LIB$INITIALIZE.
 
           В табл. 11 приводятся примеры для основных языков сис-
 
      темы МОС ВП.
 


                                - 101 -
 
                           00152-01 97 08
 
 
                                                       Таблица 11
 
                Инициализация статической памяти
 
      -----------------------------------------------------------
             !                        !      !
             !                        !Прои- !
             !                        !      !
      Язык   !                        !нициа-!
             !                        !      !
      про-   !                        !лизи- !
             !                        !      !
      грамми-!      Оператор          !рован-!   Момент инициали-
             !                        !      !
      рования!                        !ное   !      зации
             !                        !      !
             !                        !значе-!
             !                        !      !
             !                        !ние   !
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      АДА    !  X:INTEGER:=1          !  1   !  Момент реализации
             !                        !      !
             !                        !      ! (выполнения)
             !                        !      !
      -----------------------------------------------------------
             !
      Бейсик ! Бейсик не позволяет иметь статическую память
             !
             ! внутри модуля, только общая статическая память
             !
      -----------------------------------------------------------
             !                        !      !
      Блисс  ! OWN DAT;               !  0   !На этапе компиляции
             !                        !      !
             ! OWN DAT INITIAL(0):    !  0   !На этапе компиляции
             !                        !      !
             ! OWN DAT INITIAL(100)   !  100 !На этапе компиляции
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      Кобол  ! 01 NUM PIC             !  0   !На этапе компиляции
             !                        !      !
             ! 01 NUM PIC 9 VALUE 0   !  0   !На этапе компиляции
             !                        !      !
             ! 01 NUM PIC 9(3) VALUE  !  100 !На этапе компиляции
             !                        !      !
             ! 100                    !      !
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      Фортран! INTEGER.4 DAT          !  0   !На этапе компиляции
             !                        !      !
             ! INTEGER.4 DAT/0/       !  0   !На этапе компиляции
             !                        !      !
             ! DATA DAT/0/            !  0   !На этапе компиляции
             !                        !      !
             ! DATA DAT/100/          !  100 !На этапе компиляции


                                - 102 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 11
      -----------------------------------------------------------
             !                        !      !
             !                        !Прои- !
             !                        !      !
      Язык   !                        !нициа-!
             !                        !      !
      про-   !                        !лизи- !
             !                        !      !
      грамми-!      Оператор          !рован-!   Момент инициали-
             !                        !      !
      рования!                        !ное   !      зации
             !                        !      !
             !                        !значе-!
             !                        !      !
             !                        !ние   !
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      Макро- ! DAT: BLKL 1            !  0   !На этапе компиляции
             !                        !      !
      ассем- ! DAT: LONG 0            !  0   !На этапе компиляции
             !                        !      !
      блере  ! DAT: LONG 100          !  100 !На этапе компиляции
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      Паскаль! DAT:[STATIC]INTEGER:   !  0   !На этапе компиляции
             !                        !      !
             ! DAT:[STATIC]INTEGER:=0;!  0   !На этапе компиляции
             !                        !      !
             ! DAT:INTEGER:=100;      !  100 !На этапе компиляции
             !                        !      !
      -----------------------------------------------------------
             !                        !      !
      ПЛ/1   ! STATIC   INIT(2)       !  2   !На этапе компиляции
             !                        !      !
             ! EXTERNAL INIT(3)       !  3   !На этапе компиляции
             !                        !      !
             ! GLOBALDEFINIT(4)       !  4   !На этапе компиляции
             !                        !      !
             ! GLOBALREFINIT(5)       !  5   !На этапе компиляции
 
 
 
           3.2.2. Проверка и установка флага первого входа
 
 
           Чтобы выполнить инициализацию при первом входе, проце-
 
      дура может проверить, а затем установить в  единицу  стати-
 
      чески  распределенный  флаг  первого  входа.  Эта  операция
 
      производится при каждом вызове процедуры. Данный флаг  ини-
 
      циализируется нулем на  этапе  компиляции  или  компоновки.


                                - 103 -
 
                           00152-01 97 08
 
 
      установка и проверка значения флага  с  помощью  инструкции
 
      "переход по условленному разряду и установка" (BBSS) гаран-
 
      тирует однократное выполнение  инициализации  (можно  также
 
      использовать команду BBSSI или процедуру LIB$BBSSI исполни-
 
      тельной библиотеки).
 
           Если же в используемом языке программирования отсутст-
 
      вует доступ к командам СМ 1700,  а  процедура  должна  быть
 
      реентерабельной по AST, то она должна  выполнять  следующие
 
      шаги (см. подраздел 3.3):
 
           1) проверка флага первого входа;
 
           2) если флаг первого входа  установлен,  инициализация
 
      выполнена;
 
           3) если флаг первого входа не  установлен,  заблокиро-
 
      вать асинхронные системные прерывания. Запомнить предыдущее
 
      состояние, в котором были разрешены  асинхронные  системные
 
      прерывания, и повторить проверку флага;
 
           4) если теперь флаг первого входа установлен,  инициа-
 
      лизация была выполнена асинхронным  системным  прерыванием,
 
      которое произошло в промежутке между первой проверкой флага
 
      и блокированием асинхронных системных прерываний; разрешить
 
      асинхронные системные прерывания, если они  были  разрешены
 
      до блокировки (по предыдушему шагу 3). Теперь инициализация
 
      завершена;
 
           5) если флаг первого входа  не  установлен,  выполнить
 
      инициализацию;
 
           6) установить флаг;
 
           7)  деблокировать  асинхронные  системные  прерывания,
 
      если они были разрешены по предыдущему состоянию; инициали-
 
      зация завершена.
 
           Примечание. Асинхронные системные  прерывания  следует


                                - 104 -
 
                           00152-01 97 08
 
 
      деблокировать только в том случае (шаг 4 или шаг  7),  если
 
      они были деблокированы до шага 3.  Системная  обслуживающая
 
      программа $SETAST, используемая для блокирования  асинхрон-
 
      ных системных  прерываний,  указывает,  были  ли  разрешены
 
      асинхронные системные прерывания при вызове процедуры.
 
           Пример иллюстрирует использование флага первого  входа
 
      программой распределения ресурса на языке Паскаль:
 
      (+)
 
      ( программа для демонстрации использования флага первого
 
      ( входа при распределении ресурса. Данная программа являет-
 
      ( ся реентерабельной только по AST.
 
      (-)
 
      PROGRAM ALLOCATE;
 
      CONST
 
          VM_SIZE = 512;
 
      VAR
 
          INITIALIZED : BOOLEAN := FALSE;
 
          VM_ADDRESS : INTEGER := 0;
 
          AST_STATUS : INTEGER := 0;
 
          VM_STATUS : INTEGER := 0;
 
          DISABLE : INTEGER := 0;
 
      FUNCTION LIB$GET_VM (SIZE:INTEGER; VAR ADDR:INTEGER):
 
          INTEGER;EXTERNAL;
 
      FUNCTION SYS$SETAST (VAR STATUS:INTEGER):INTEGER;
 
          EXTERNAL;
 
      BEGIN
 
          (+)
 
          ( проверка флага первого входа. Если флаг установлен,
 
          ( инициализация была уже выполнена.
 
          (-)

                             
                                - 105 -
 
                           00152-01 97 08
 
 
          IF NOT (INITIALIZED)
 
          THEN
 
             BEGIN
 
             (+)
 
             ( заблокировать асинхронные системные прерывания и
 
             ( запомнить предыдущее состояние.
 
             (-)
 
             AST_STATUS := SYS$SETAST (DISABLE):
 
             (+)
 
             ( теперь еще раз проверить флаг. Если он сейчас ус-
 
             ( тановлен, инициализация была выполнена в результа-
 
             ( те другого обращения к данной процедуре в промежу-
 
             ( тке между тем моментом, когда флаг проверялся пер-
 
             ( вый раз, и текущим моментом. В противном случае
 
             ( инициализация выполняется здесь.
 
             (-)
 
             IF NOT (INITIALIZED)
 
             THEN
 
                  BEGIN
 
                  (+)
 
                  ( выполнение инициализации
 
                  (-)
 
                  VM_STATUS := LIB$GET_VM (VM_SIZE, VM_ADDRESS);
 
                  (+)
 
                  ( установить флаг первого входа, указывающий,
 
                  ( что инициализация произведена.
 
                  (-)
 
                  INITIALIZED := TRUE;
 
                  END;
 
              (+)


                                - 106 -
 
                           00152-01 97 08
 
 
              ( восстановить обработку асинхронных системных пре-
 
              ( рываний в соответсвии с предыдущим состоянием.
 
              (-)
 
              AST_STATUS := SYS$SETAST (AST_STATUS);
 
              END;
 
      END.
 
 
 
           3.2.3. Использование LIB$INITIALIZE
 
 
           Один из способов возможной  инициализации  значения  в
 
      текущий  момент  заключается  в   использовании   процедуры
 
      LIB$INITIALIZE исполнительной библиотеки.
 
           Если в процедуре пользователь устанавливает  программу
 
      обработки (исключительного  состояния)  посредством  вызова
 
      LIB$INITIALIZE перед  основной  программой,  работа  данной
 
      программы обработки может конфликтовать с другими  програм-
 
      мами обработки состояний, которые установлены другими  про-
 
      цедурами до вызова основной программы.
 
           Существуют определенные  обстоятельства,  при  которых
 
      может понадобиться  произвести  инициализацию  значения  во
 
      время прогона программы. Примером значения,  которое  может
 
      потребоваться инициализировать на этапе прогона, может слу-
 
      жить начальное значение для генератора случайных чисел.
 
           Существует шесть действий, которые надлежит  выполнить
 
      при использовании процедуры LIB$INITIALIZE для  инициализа-
 
      ции значения на этапе прогона:
 
           1) написать основную программу;
 
           2) написать процедуру инициализации;
 
           3) написать на Макроассемблере  или  Блиссе  программу
 
      для добавления адреса такой процедуры инициализации к прог-
 


                                - 107 -
 
                           00152-01 97 08
 
 
      раммной секции (PSECT) LIB$INITIALIZE;
 
           4) провести компиляцию процедуры инициализации, основ-
 
      ной программы и программы, написанной на Макроассемблере;
 
           5)  скомпоновать  процедуру  инициализации,   основную
 
      программу и программу на Макроассемблере;
 
           6) запустить основную программу.
 
           Предполагая, что  разработка  основной  программы  уже
 
      завершена, в первую очередь следует написать процедуру ини-
 
      циализации.  Если,  например,  предполагается  использовать
 
      LIB$INITIALIZE для инициализации  значения  для  генератора
 
      случайных чисел, можно  написать  процедуру  инициализации,
 
      которая в качестве исходного значения для генератора  подс-
 
      тавляет значение текущего времени. В результате будет гене-
 
      рироваться каждый раз другое исходное число  при  очередной
 
      инициализации, поскольку время постоянно  изменяется.  Одна
 
      из возможных процедур инициализации приведена в примере:
 
           100 !+
 
               ! подпрограмма инициализации. Общий элемент данных
 
               ! SEED - инициализируется по числу секунд времени
 
               ! центрального процессора, которое уже использова-
 
               ! но данным процессором.
 
               SUB MY_INIT_ROOTINE(ONE,TWO,THREE,FOUR,FIVE,SIX)
 
               COMMON (MY_DATA) LONG SEED
 
               PRINT "NOW IN INITIALIZATION ROUTINE."
 
               CURRENT_TIME = TIME (1)
 
               SEED = CURRENT_TIME
 
               END SUB
 
           После того, как описана процедура инициализации,  сле-
 
      дует написать  программу  на  Макроассемблере,  которая  бы
 
      добавляла адрес такой процедуры инициализации к программной


                                - 108 -
 
                           00152-01 97 08
 
 
      секции (PSECT) LIB$INITIALIZE. Формат  такой  программы  на
 
      Макро весьма прост, что видно из примера:
 
 
 
      ;+
 
      ; ссылки на используемые внешние программы.
 
      ;-
 
              .EXTRN LIB$INITIALIZE
 
              .EXTRN MY_INIT_ROUTINE
 
      ;+
 
      ; добавление к PSECT LIB$INITIALIZE.
 
      ;-
 
              .PSECT LIB$INITIALIZE USR,CBL,NOEXE,NOWRT,LONG
 
              .ADDRESS MY_INIT_ROUTINE
 
              .END
 
           Изменения в данной программе  на  Макроассемблере  для
 
      использования в собственных процедурах связаны с подстанов-
 
      кой имени процедуры инициализации вместо MY_INIT_ROUTINE.
 
           После того, как  написаны  процедура  инициализации  и
 
      программа на Макроассемблере для добавления адреса "диспет-
 
      черизации" к PSECT LIB$INITIALIZE, следует просто скомпоно-
 
      вать и запустить программу. В качестве  основной  программы
 
      для примера используется следующая программма на Бейсике:
 
            !+
 
      10    ! основная программа. Печатается значение переменной
 
            ! SEED.
 
            ! компоновщик изначально полагает это значение равным
 
            ! нулю, но так как используется процедура LIB$INITIA-
 
            ! LIZE, перед тем, как управление будет передано в
 
            ! в данное место, выполняется программа инициализации
 
            ! и значение переменной SEED изменяется на некоторое


                                - 109 -
 
                           00152-01 97 08
 
 
            ! случайное значение.
 
            !-
 
            COMMON (MY_DATA) LONG SEED
 
            PRINT "NOW IN MAINLINE. THE SEED IS INITIALIZED TO:";
 
            SEED
 
      32767 END
 
           Для того чтобы запустить процедуру  LIB$INITIALIZE  и,
 
      таким  образом,  проинициализировать  значение   переменной
 
      SEED, вводятся следующие команды:
 
      $ BASIC MATN
 
      $ BASIC INIT
 
      $ MACRO LIBRARY
 
      $ LINK MAIN, INIT, LIBRARY
 
      $ RUN MAIN
 
           В результате  выполнения  указанных  шагов  получается
 
      выходная информация вида:
 
           NOW IN INITIALIZATION ROUTINE.
 
           NOW IN MAINLINE. THE SEED IS INITIALIZED TO: 4099
 
 
 
           3.3. Написание программы, реентерабельной по AST
 
 
           В данном подразделе описывается  методика  кодирования
 
      модульных процедур, в которых используется механизм  преры-
 
      вания системы МОС ВП посредством асинхронных системных пре-
 
      рываний либо обеспечивается возможность его использования в
 
      вызывающих программах.
 
           Все модульные процедуры должны быть реентерабельными с
 
      точки зрения обработки асинхронных системных  прерываний  с
 
      тем, чтобы их можно было вызвать из любой  программы.  Если
 
      процедура не является реентерабельной по AST либо  вызывает
 


                                - 110 -
 
                           00152-01 97 08
 
 
      некоторую процедуру, которая таковой не является, это  обс-
 
      тоятельство должно быть отражено в программной документации
 
      с тем, чтобы предупредить других пользователей и предотвра-
 
      тить использование такой процедуры.
 
 
 
           3.3.1. Определение асинхронного системного прерывания
 
 
           Асинхронное системное прерывание (AST) - это  механизм
 
      системы МОС ВП, обеспечивающий программное  прерывание  при
 
      возникновении внешнего события. Одним из примеров  прерыва-
 
      ния такого вида может служить нажатие пользователем  клавиш
 
      CTRL/C на терминале.  При  возникновении  внешнего  события
 
      операционная система МОС ВП прерывает  выполнение  текущего
 
      процесса и обращается к указанной пользователем  процедуре.
 
      Такая процедура как раз и есть то, что называется  програм-
 
      мой обработки асинхронных системных прерываний.
 
           Некоторые средства системного обслуживания МОС ВП поз-
 
      воляют внешнему событию прерывать процесс. Так как прерыва-
 
      ние возникает вне относящейся к выполнению процесса  после-
 
      довательности событий, такой механизм прерывания называется
 
      "асинхронным" системным прерыванием. По  асинхронному  сис-
 
      темному прерыванию происходит передача управления программе
 
      обработки асинхронного системного прерывания, которая  обс-
 
      луживает событие.  Такая  программа  обработки  асинхронных
 
      системных прерываний может обращаться к другим  процедурам,
 
      включая библиотечные процедуры.
 
           Говорят, что программа обработки асинхронных системных
 
      прерываний, указываемая пользователем, и  те  процедуры,  к
 
      которым она обращается,  работают  на  уровне  асинхронного
 
      системного прерывания. Находящийся на  уровне  асинхронного
 


                                - 111 -
 
                           00152-01 97 08
 
 
      системного прерывания процесс не может быть прерван  другим
 
      прерыванием в том же  режиме  доступа.  Процесс  продолжает
 
      выполняться до своего  завершения  на  уровне  асинхронного
 
      прерывания до того, как возобновится  выполнение  процедуры
 
      не уровня асинхронного системного прерывания.
 
           Таким образом,  процесс  выполняется  либо  на  уровне
 
      асинхронного  системного  прерывания,  либо  не  на  уровне
 
      асинхронного системного прерывания и, следовательно, содер-
 
      жит две "цепи выполнения", по одной цепи (последовательнос-
 
      ти) для каждого уровня. Следует иметь  в  виду,  что  такие
 
      уровни представляют цепи одного и того же  процесса,  а  не
 
      отдельные процессы.
 
           После того, как программа обработки  асинхронных  сис-
 
      темных прерываний завершит обслуживание события, она  возв-
 
      ратит управление вызвавшей ее программе. Прерванные  проце-
 
      дуры продолжают свое выполнение с точки прерывания.
 
           Например, можно обратиться к программе системного обс-
 
      луживания "установить таймер"  ($SETIMR)  для  того,  чтобы
 
      указать адрес той процедуры  уровня  асинхронных  системных
 
      прерываний, которую следует исполнить по истечении заданно-
 
      го промежутка времени. В указанное время  система  сгенери-
 
      рует асинхронное системное прерывание, остановив  исполняе-
 
      мую в данный момент процедуру  и  обратившись  к  указанной
 
      программе обработки асинхронных системных прерываний.
 


                                - 112 -
 
                           00152-01 97 08
 
 
           3.3.2. Реентерабельность    по    AST     и     полная
 
      реентерабельность
 
 
           Процедура считается реентерабельной по AST,  если  она
 
      удовлетворяет следующим условиям:
 
           - ее можно прервать в любой точке, обеспечивая возмож-
 
      ность вызова ее же или любой взаимосвязанной с ней процеду-
 
      ры (повторный вход);
 
           - она будет работать правильно при  ее  продолжении  с
 
      точки прерывания.
 
           Нельзя путать термин "реентерабельность  по  AST  "  с
 
      термином "полная реентерабельность".  Полная  реентерабель-
 
      ность требует удовлетворения набора более жестких условий.
 
           В среде повторной входимости с точки зрения  обработки
 
      асинхронных системных прерываний предполагается, что цепоч-
 
      ка уровня AST завершится независимо от того, встретится  ли
 
      заблокированный ресурс или нет.  Если  цепочка  уровня  AST
 
      обнаруживает заблокированный  ресурс,  предполагается,  что
 
      выделится "новый" ресурс или что будет возвращено сообщение
 
      об ошибке.  Никогда  не  предполагается  ожидание  ресурса,
 
      который заблокирован не на уровне AST.
 
           В среде полной реентерабельности все цепочки обрабаты-
 
      ваются одинаково при обнаружении заблокированного  ресурса:
 
      они будут ожидать  освобождения  ресурса.  В  среде  полной
 
      реентерабельности цепочкам асинхронных системных прерываний
 
      не выдается какой-либо специальной обработки. Примером пол-
 
      ностью реентерабельной среды может служить среда языка  АДА
 
      системы МОС ВП. В ней может  быть  более  двух  параллельно
 
      исполняемых цепочек, и каждая  цепочка  поочередно  продви-
 
      гается к завершению.
 


                                - 113 -
 
                           00152-01 97 08
 
 
           Примечание. Желательно, чтобы будущие программы  удов-
 
      летворяли  жестким  требованиям  полной  реентерабельности.
 
      Полная реентерабельность важна для процедур, которые  будут
 
      вызываться из среды с множеством цепочек, какими, например,
 
      являются задачи, запрограммированные на языке АДА.
 
 
 
           3.3.3. Основные  положения  по   написанию   модульных
 
      процедур, рeентерабельных по AST
 
 
           Чтобы использовать асинхронные  системные  прерывания,
 
      следует написать программу обработки асинхронных  системных
 
      прерываний, которая получит управление на уровне  асинхрон-
 
      ных системных прерываний. Программу  обработки  асинхронных
 
      системных прерываний можно запрограммировать на любом  язы-
 
      ке. Поскольку особенности написания обработчика асинхронных
 
      системных прерываний отличаются при использовании того  или
 
      иного языка программирования, следует более подробно  озна-
 
      комиться со справочным руководством по языку программирова-
 
      ния, на котором пишется программа.
 
           В общем случае программа обработки асинхронных систем-
 
      ных прерываний должна  соответствовать  следующим  основным
 
      положениям:
 
           - она должна быть отделена от той  процедуры,  которая
 
      выполняется в данный момент времени;
 
           - она не должна изменять данные или  команды,  которые
 
      используются прерванной  процедурой  либо  вызывающими  эту
 
      процедуру;
 
           - программа обработки асинхронных системных прерываний
 
      должна вызываться с помощью  команды  CALLG  или  CALLS,  а
 
      управление должна возвращать с помощью команды RET;
 


                                - 114 -
 
                           00152-01 97 08
 
 
           - если изменяется содержимое регистров, отличных от R0
 
      и R1, программа должна устанавливать  биты  в  маске  точки
 
      входа для того, чтобы сохранить содержимое таких регистров;
 
           - если программа вызывает какие-либо другие процедуры,
 
      все они должны быть реентерабельными по AST;
 
           - программа обработки асинхронных системных прерываний
 
      не может останавливаться либо использовать "занят,  обожди-
 
      те" в целях предотвращения вызова до  того  момента,  когда
 
      уровень не асинхронного системного прерывания не выйдет  из
 
      критичного участка программы.  После  того,  как  программа
 
      обработки асинхронного системного прерывания  начала  рабо-
 
      тать, ее  нельзя  прервать  какой-либо  программой  другого
 
      уровня. И действительно,  единственная  программа,  которая
 
      может прервать программу обработки асинхронного  системного
 
      прерывания, - это другая процедура, выполняющаяся на уровне
 
      асинхронных системных прерываний с другим режимом  доступа.
 
      Если пытаться использовать  механизм  "обождите,  занят"  и
 
      ожидать смены условия с уровня не  асинхронного  системного
 
      прерывания, на уровне  асинхронного  системного  прерывания
 
      возникает бесконечный цикл по признаку  "занят,  обождите".
 
      Процесс будет продолжать зацикливаться из-за того, что уро-
 
      вень не асинхронного системного прерывания не будет продол-
 
      жать выполняться до тех пор,  пока  не  завершится  цепочка
 
      асинхронных системных прерываний, и следовательно,  никогда
 
      не сможет изменить значение признака "обождите, занят";
 
           - пользователь не может использовать средство обслужи-
 
      вания заблокированных ресурсов для защиты ресурса, к  кото-
 
      рому происходит доступ с уровня не асинхронного  системного
 
      прерывания, от доступа с уровня асинхронных системных  пре-
 
      рываний.  Средство  обслуживания  заблокированных  ресурсов


                                - 115 -
 
                           00152-01 97 08
 
 
      разработано в целях блокировки ресурсов  различных  процес-
 
      сов, а не различных цепочек (асинхронных системных прерыва-
 
      ний и не асинхронных системных прерываний) одного и того же
 
      процесса;
 
           - следует избегать использования  статической  памяти.
 
      Процедура, которая не использует статической памяти,  обра-
 
      щается только к процедурам, реентерабельным по  AST,  и  не
 
      выполняет адресации верхнего уровня, автоматически является
 
      реентерабельной по AST.
 
 
 
           3.3.4. Ликвидация    условий     соперничества     при
 
      параллельном доступе
 
 
           При  использовании  асинхронных  системных  прерываний
 
      могут встретиться две проблемы.  Они  называются  условиями
 
      соперничества и тупиковыми ситуациями. Условие соперничест-
 
      ва возникает, если программа обрабоки асинхронных системных
 
      прерываний пытается воспользоваться неразделяемым ресурсом,
 
      который уже  задействован  цепочкой  выполнения  не  уровня
 
      асинхронного системного прерывания.
 
           Если разрешить программе обработки асинхронных систем-
 
      ных прерываний ожидать освобождения ресурса (например, пос-
 
      редством ожидания флага события, который должен быть  уста-
 
      новлен программой не уровня асинхронного системного  преры-
 
      вания с тем же режимом доступа), то возникнет некий вариант
 
      тупиковой  ситуации.  Тупиковая  ситуация  возникает  из-за
 
      того, что программа не уровня асинхронного системного  пре-
 
      рывания  не  может  выполняться  с  тем,  чтобы  освободить
 
      ресурс, причем до тех пор, пока  не  закончит  свою  работу
 
      программа уровня асинхронных системных прерываний. Програм-
 


                                - 116 -
 
                           00152-01 97 08
 
 
      ма же уровня асинхронных системных прерываний не может быть
 
      продолжена из-за того,  что  программа  другого  уровня  по
 
      существу заблокировала ресурс.
 
           Условие соперничества возникает при  попытке  осущест-
 
      вить доступ или изменить одну и ту же информацию  в  стати-
 
      ческой памяти из программы как уровня асинхронных системных
 
      прерываний, так и другого уровня некоторого процесса.  Нап-
 
      ример, если начинает отрабатываться  асинхронное  системное
 
      прерывание в тот момент, когда происходит изменение  инфор-
 
      мации в статической памяти не на уровне асинхронных систем-
 
      ных прерываний, такая информация может остаться в некотором
 
      неустойчивом состоянии, пока отработает программа обработки
 
      асинхронных системных прерываний. Для того  чтобы  избежать
 
      условия  соперничества,  следует  разрешать  только   одной
 
      цепочке процесса в каждый данный момент времени производить
 
      изменения информации.
 
           Если процедура не изменяет информацию ячеек  статичес-
 
      кой памяти, такая процедура одновременно является реентера-
 
      бельной по  AST  и  полностью  реентерабельной.  Существует
 
      целый ряд способов, с помощью  которых  в  процедуре  можно
 
      исключить конфликтные ситуации, связанные  с  доступом  или
 
      изменением информации в статической памяти:
 
           - выполнять все операции доступа  либо  модификации  в
 
      одной непрерываемой инструкции (данная методика также  поз-
 
      воляет получать полностью реентерабельные процедуры);
 
           - выделять параллельные запросы на доступ к информации
 
      с помощью инструкций "проверить и установить" при  входе  и
 
      при выходе из области хранения информации. Затем  процедура
 
      может сообщить об ошибке или попытаться повторить  операцию
 
      (если это возможно) при обнаружении параллельных доступов;


                                - 117 -
 
                           00152-01 97 08
 
 
           - хранить счетчик вызовов, который  увеличивается  при
 
      вызове процедуры  и  уменьшается  при  возврате  процедурой
 
      управления (на выходе из процедуры). Счетчик используется в
 
      качестве индекса в отдельно выделеных полях;
 
           - блокировать  асинхронные  системные  прерывания  при
 
      входе и восстанавливать состояние разрешения таких прерыва-
 
      ний (деблокировать) при выходе.
 
 
 
           3.3.4.1. Выполнение операций доступа посредством одной
 
      инструкции
 
 
           В некоторых прикладных программах корректирование дан-
 
      ных в статической области памяти можно выполнить с  помощью
 
      одной непрерываемой инструкции. Однако данный способ  отно-
 
      сится только к программам на Макроассемблере, и даже в этом
 
      случае он неприменим для моделируемых инструкций.
 
           Можно, например, воспользоваться  инструкциями  поста-
 
      новки в очередь для обслуживания скомпилированного списка в
 
      одной инструкции вместо того, чтобы  изменять  поля  ссылок
 
      вперед и назад списка нескольких инструкций. Можно восполь-
 
      зоваться одной командой обслуживания очереди в начале  про-
 
      цедуры для удаления одной секции, а другой  командой  можно
 
      воспользоваться для того, чтобы  в  конце  работы  вставить
 
      секцию обратно в очередь.
 
           Пока секция не удалена  из  очереди,  процедура  может
 
      изменять в ней информацию. Если асинхронное системное  пре-
 
      рывание возникает в тот момент,  когда  секция  удалена  из
 
      очереди, вместо нее используется другая секция данных,  тем
 
      самым избегаются конфликтные ситуации с прерванной процеду-
 
      рой.
 


                                - 118 -
 
                           00152-01 97 08
 
 
           Пример иллюстрирует процедуру, реентерабельную по AST,
 
      в которой используются инструкции  работы  с  очередью  для
 
      управления распределением блоков из квадрослов:
 
            .PSECT _LIB_DATA PIC,USR,CON,REL,LCL,NOSHR,NOEXE,
 
                   RD,WRT
 
      FLAG: .LONG  0                ;флаг первого входа.
 
      Q_HED .LONG  0,0
 
            .PSECT _LIB_CODE PIC,USR,CON,REL,LCL,SHR,EXE,RD,NOWRT
 
            .ENTRY LIB_GET_X,^M<>
 
            BBC    FLAG, FIRST      ;переход только при первом
 
                                    ;входе.
 
      TRY:  REMQUE @Q_HED, R0       ;в регистре R0 адрес очере-
 
                                    ;ди.
 
            BVS    10$              ;переход, если очередь пус-
 
                                    ;та, и заполнить.
 
            RET
 
      10$   BSBB   FILL             ;заполнить очередь.
 
            BRB    TRY              ;попытаться еще раз.
 
      ;+
 
      ; здесь только при первом вызове.
 
      ;-
 
      FIRST:  $SETAST #0              ;заблокировать асинхронные
 
                                      ;системные прерывания, в
 
                                      ;регистре R0- старое значе-
 
                                      ;ние.
 
              BBSS   FLAG, 20$        ;переход, если уже установ-
 
                                      ;лен.
 
              MOVAL  Q_HED,  Q_HED    ;сделать очередь пустой.
 
              MOVAL  Q_HED,  Q-HED+4  ;то же для указателя обрат-
 
                                      ;ной ссылки.


                                - 119 -
 
                           00152-01 97 08
 
 
              BSBB   FILL             ;заполнить очередь.
 
      20$:    CMPL   #SS$_WASSET, R0  ;ранее были разрешены асин-
 
                                      ;хронные системные преры-
 
                                      ;вания?
 
              BNEQ   TRY              ;нет, оставить заблокиро-
 
                                      ;ванными, повторить попыт-
 
                                      ;ку.
 
              $SETAST 1               ;да, деблокировать (разре-
 
                                      ;шить) асинхронные систем-
 
                                      ;ные прерывания.
 
              BRB    TRY              ;попытаться еще раз.
 
      FILL:   GET SPACE FOR 10 GUADWORDS BY CALLING LIB$GET_VM
 
              (получить место под 10 квадрослов, обратившись к
 
              LIB$GET_VM)
 
              AND INSERT IN GUEUE UNING INSQUE
 
              (и вставить в очередь с помощью INSQUE)
 
              RSB
 
           Примечание. Данный пример можно было бы перепрограмми-
 
      ровать, используя REMQHI и INSQHI, и при этом отпадет необ-
 
      ходимость во флаге первого входа.
 
 
 
           3.3.4.2. Использование   инструкций    "проверить    и
 
      установить"
 
 
           Один из способов исключения возможности  возникновения
 
      соперничества или тупиковой ситуации заключается в  исполь-
 
      зовании инструкций "проверить и установить" для обнаружения
 
      параллельного доступа. Можно обнаружить параллельный доступ
 
      к статической памяти и на уровне асинхронных системных пре-
 
      рываний, и не на уровне асинхронных  системных  прерываний,
 


                                - 120 -
 
                           00152-01 97 08
 
 
      если в процедуру включить следующие действия:
 
           - поместить инструкцию перехода по установленному биту
 
      и последующей установки бита  (BBSS  или  BBSSI)  сразу  же
 
      перед тем, как процедура осуществляет доступ к  статической
 
      памяти;
 
           - произвести доступ и/или изменить информацию в стати-
 
      ческой памяти;
 
           - поместить инструкцию перехода по сброшенному биту  и
 
      последующего сброса бита (BBCC или BBCCI)  сразу  же  после
 
      того, как процедура завершит доступ к статической памяти.
 
           Инструкцией BBSS обнаруживается, что конфликт в  связи
 
      с параллельным доступом произошел незадолго  до  того,  как
 
      осуществлен  доступ  к  статической  памяти.  Если   память
 
      используется множеством процессоров,  следует  использовать
 
      инструкции BBSSI и BBCCI.
 
           Существует два варианта разрешения конфликтных  ситуа-
 
      ций, возникающих в связи с параллельным  доступом,  которые
 
      обнаруживаются посредством инструкций BBSS и BBCC:
 
           1) использование независимых, статически  распределен-
 
      ных областей для хранения информации как на  уровне  асинх-
 
      ронных системных прерываний, так и не на уровне асинхронных
 
      системных прерываний. Если  инструкция  BBSS  обнаруживает,
 
      что конфликт в связи с параллельным  доступом  произошел  в
 
      самом  начале,  можно  воспользоваться  второй   выделенной
 
      областью. Следует отметить, что данный способ не  работает,
 
      если между выполнением инструкций  BBSS  и  BBCC  возникает
 
      условие исключительной ситуации либо если  в  процедуре  не
 
      установлена программа обработки исключительных условий. Это
 
      происходит из-за того, что программа обработки исключитель-
 
      ных условий,  установленная  вызывающей  программой,  может


                                - 121 -
 
                           00152-01 97 08
 
 
      одновременно также вызывать данную процедуру пользователя;
 
           2) повторное выполнение  процедуры,  если  обнаружится
 
      параллельный  доступ.  Если  командой  BBCC  обнаруживается
 
      параллельность, нужно вернуться на начало процедуры и  пов-
 
      торить работу еще раз.
 
           Пример иллюстрирует второй способ  (в  этой  процедуре
 
      LIB_GET_INUM, написанной на Макроассемблере, распределяются
 
      и освобождаются числа-идентификаторы):
 
       .TITLE LIB_GET_INUM выделить и освободить числа-иденти-
 
                                          ;фикаторы 1-10.
 
      TAB:    .WORD   0                   ;карта занятости флагов
 
              .ENTRY  LIB_GET_INUM, ^M<>
 
      10$:    FFC     #1, #10,TAB, R0     ;найти первый свободный
 
                                          ;идентификатор - число.
 
              BEQ     20$                 ;переход, если свобод-
 
                                          ;ных нет.
 
              BBSS    R0, TAB, 10$        ;указать, что число-
 
                                          ;идентификатор исполь-
 
                                          ;зуется.
 
              MOVL    R0, 04(AP)          ;вернуть найденный
 
                                          ;идентификатор-число.
 
              MOVL    #1, R0              ;указать успешность
 
                                          ;операции.
 
              RET
 
      20$:    CLRL    04(AP)              ;вернуть 0
 
              CLRL    R0                  ;указать на неудачу.
 
              RET
 
              .END
 


                                - 122 -
 
                           00152-01 97 08
 
 
           3.3.4.3. Обслуживание   счетчика    текущих    вызовов
 
      программы
 
 
           Если базу данных необходимо сохранять между  вызовами,
 
      можно отслеживать вызовы процедуры пользователя,  используя
 
      счетчик текущих  вызовов.  Перед  доступом  к  базе  данных
 
      содержимое счетчика  инкрементируется  и  используется  для
 
      индексации таблицы адресов для отдельных баз  данных.  Сле-
 
      дует контролировать, чтобы значение счетчика  не  превысило
 
      длины таблицы. После того, как произошел доступ к базе дан-
 
      ных, содержимое счетчика декрементируется.
 
           Данный способ имеет то преимущество перед  способом  с
 
      инструкциями BBXX, что здесь можно обрабатывать более  двух
 
      уровней повторного входа. Вместе с тем, он  менее  надежен,
 
      поскольку исключительное состояние может привести  к  тому,
 
      что счетчик никогда не уменьшится, что приведет к возможной
 
      неверной работе процедуры. Последнего можно избежать,  если
 
      в процедуре установить программу  обработки  исключительных
 
      состояний.
 
 
 
           3.3.4.4. Блокирование асинхронных системных прерываний
 
 
           Процедура считается реентерабельной по AST также в том
 
      случае, когда асинхронные системные прерывания  блокируются
 
      на время выполнения критичных  участков  программы.  Однако
 
      данный способ обеспечения реентерабельности по  AST  приме-
 
      нять не рекомендуется.
 
           Иногда единственным способом избежать  условия  парал-
 
      лельности является блокирование асинхронных системных  пре-
 
      рываний на время доступа к статической памяти и  восстанов-
 
      ление  состояния  деблокированности  асинхронных  системных


                                - 123 -
 
                           00152-01 97 08
 
 
      прерываний после того, как завершено выполнение  критичного
 
      участка программы. Однако данный способ может  отрицательно
 
      сказываться на работе программ реального  времени,  исполь-
 
      зующих асинхронные системные прерывания. Системная обслужи-
 
      вающая программа $SETAST, которая используется для блокиро-
 
      вания и деблокирования  асинхронных  системных  прерываний,
 
      занимает много времени  на  свою  работу.  Поэтому  следует
 
      избегать  блокирования  асинхронных  системных   прерываний
 
      (подпункты 3.3.4.1-3.3.4.3).
 
           Следует свести к  минимуму  количество  инструкций,  в
 
      ходе выполнения которых блокируются  асинхронные  системные
 
      прерывания. Перед тем, как заблокировать  асинхронные  сис-
 
      темные прерывания, необходимо  задать  программу  обработки
 
      исключительных состояний для того, чтобы восстановить  уро-
 
      вень асинхронных системных прерываний в случае  возникнове-
 
      ния исключительного состояния или разворота стека.
 
           Пример демонстрирует возможное  использование  $SETAST
 
      для блокирования асинхронных системных прерываний и  после-
 
      дующего восстановления предыдущего состояния для их  дебло-
 
      кирования:
 
      !+
 
      !данная программа демонстрирует использование программы
 
      !системного обслуживания SYS$SETAST для блокирования и
 
      !деблокирования асинхронных системных прерываний.
 
      !-
 
              INCLUDE '($SSDEF)'
 
              INTEGER*4 SYS$SETAST
 
      !+
 
      !отключить асинхронные системные прерывания и запомнить
 
      !предыдущее состояние.


                                - 124 -
 
                           00152-01 97 08
 
 
 
      !-
 
              ISTAT=SYS$SETAST (%VAL(0))
 
      !+
 
      !операторы программы, во время выполнения которых желатель-
 
      !но, чтобы асинхронные системные прерывания были заблокиро-
 
      !ваны.
 
      !
 
      !если ранее асинхронные системные прерывания были разре-
 
      !шены (деблокированы), повторно разрешить их.
 
      !-
 
           IF (ISTAT .EQ. SS$_WASSET) CALL SYS$SETAST (%VAL(1))
 
              END
 
 
           3.3.5. Выполнение  операций  ввода-вывода  на   уровне
 
      асинхронных системных прерываний
 
 
           Если процедура выполняет ввод-вывод  с  использованием
 
      средств системного обслуживания СУД-32, необходимо  придер-
 
      живаться ряда приемов программирования в целях  обеспечения
 
      реентерабельности процедуры с точки зрения обработки асинх-
 
      ронных системных прерываний:
 
           1) при открытии постоянных файлов процесса, таких  как
 
      SYS$INPUT, SYS$OUTPUT, SYS$COMMAND или  SYS$ERROR,  следует
 
      проверить  наличие  состояния  ошибки  СУД-32  в  процедуре
 
      RMS$_ACT (активное состояние) после выполнения каждой прог-
 
      раммы обслуживания $CREATE или $OPEN. Наличие такой  ошибки
 
      свидетельствует о том, что операция записи уже  начата  для
 
      постоянного файла процесса. Ошибка не возникает для файлов,
 
      которые не являются постоянными файлами процесса,  а  прог-
 
      рамма обслуживания $OPEN соответствует ограничениям  разде-
 


                                - 125 -
 
                           00152-01 97 08
 
 
      ленного доступа к файлу, которые могут быть наложены преды-
 
      дущей программой $OPEN. Если возникает данная ошибка, нужно
 
      выполнить команду $WAIT, используя тот же  блок  доступа  к
 
      файлу (FAB). При возврате управления  в  процедуру  следует
 
      применить программу обслуживания $CREATE или $OPEN еще раз.
 
      Данную последовательность операций повторяют  до  тех  пор,
 
      пока она не завершится успешно;
 
           2)  при  выполнении  ввода-вывода  записей  для  файла
 
      произвольного типа надо проверить наличие состояния  ошибки
 
      СУД-32 в процедуре RMS$_RSA (активный поток записей)  после
 
      каждой программы обслуживания $GET или $PUT. Данная  ошибка
 
      свидетельствует о том, что операция с  записью  уже  начата
 
      для данного файла. При  наличии  ошибки  следует  выполнить
 
      команду $WAIT, используя  тот  же  блок  доступа  к  записи
 
      (RAB). При возврате  управления  в  процедуру  нужно  снова
 
      выполнить программы обслуживания $GET или $PUT. Повторяется
 
      данная процедура до тех пор, пока она не завершится  успеш-
 
      но;
 
           3) необходимо избегать хранения данных в блоке доступа
 
      к записи (RAB), к которому  СУД-32  может  продолжать  осу-
 
      ществлять доступ. Избежать этой ситуации пользователь может
 
      одним из способов:
 
           - разместить блок доступа к записи (RAB) в стеке  так,
 
      чтобы уровень асинхронных  системных  прерываний  и  другой
 
      уровень имели независимые блоки доступа к записи;
 
           - разместить блок доступа к записи (RAB) в статической
 
      памяти и завести бит занятости. Бит занятости проверяется и
 
      устанавливается инструкцией BBSS перед тем, как  происходит
 
      доступ к блоку RAB. Если блок доступа к записи  уже  занят,
 
      процедура выполняет команду $WAIT, используя  тот  же  блок


                                - 126 -
 
                           00152-01 97 08
 
 
      доступа и записи.
 
           При синхронном вводе-выводе (ввод-вывод, который всег-
 
      да завершается до возврата управления  в  процедуру)  можно
 
      распределить блок доступа к записи любым из указанных  спо-
 
      собов. Однако первый способ представляется более  надежным,
 
      так как в нем не используется статическая память  и  потому
 
      нет опасности порчи информации при  выставлении  сигнала  о
 
      наличии исключительного состояния.
 
           При асинхронном вводе-выводе (когда управление возвра-
 
      щается в процедуру  до  завершения  операции  ввода-вывода)
 
      следует использовать второй способ.
 
 
 
           3.3.6. Обработка   условий   на   уровне   асинхронных
 
      системных прерываний
 
 
           Не следует допускать выхода обработки  исключительного
 
      состояния за пределы программы обработки  асинхронных  сис-
 
      темных прерываний, поскольку такое исключительное состояние
 
      может быть перехвачено любой активной в момент асинхронного
 
      системного прерывания процедурой. Программы обработки  иск-
 
      лючительных состояний для других  активных  процедур  могут
 
      реагировать так, как  если  бы  источником  исключительного
 
      состояния была процедура, которую они вызвали.
 
           Другая причина недопущения выхода  обработки  исключи-
 
      тельного состояния за пределы программы обработки асинхрон-
 
      ных системных прерываний связана с тем,  что  в  среде,  на
 
      базе которой происходит  выполнение  нескольких  цепочек  в
 
      одном процессе, нельзя определить, какой из стеков (цепочек
 
      выполнения) используется для передачи асинхронного  систем-
 
      ного прерывания. (асинхронное системное  прерывание  сохра-
 


                                - 127 -
 
                           00152-01 97 08
 
 
      няется в стеке любой цепочки, которая оказывается  активной
 
      в момент выработки асинхронного системного прерывания).
 
           Наилучший способ заключается в перехвате всех исключи-
 
      тельных состояний в программе обработки асинхронных систем-
 
      ных прерываний и в недопущении выхода их обработки за  пре-
 
      делы данной программы.
 
 
 
 
                           4. Тестирование
 
 
 
           Чтобы обеспечить успешность  проведения  тестирования,
 
      его следует планировать на этапе проектирования.  Предвари-
 
      тельное тестирование должно начинаться при кодировании про-
 
      цедуры. В этом смысле часть  элементов  этапа  тестирования
 
      проходят параллельно с этапом кодирования в жизненном цикле
 
      программного обеспечения.
 
           Следует проверять два основных момента:
 
           1) убедиться в том, что разработанная процедура  соот-
 
      ветствует требованиям/спецификациям. Следует тщательно про-
 
      верить каждый аспект ее функционального  назначения,  чтобы
 
      убедиться в том, что процедура выполняет все, для чего  она
 
      предназначалась, и не выполняет ничего лишнего. Те  методы,
 
      которые используются для проверки данного аспекта  процеду-
 
      ры, будут зависеть от ее функций;
 
           2) убедиться в том, что процедура модульная  и  выпол-
 
      няется без ошибок. Модульность особенно важна для тех  про-
 
      цедур, которые будут включаться  в  библиотечные  средства.
 
      Если процедура в каком-то смысле  оказывается  немодульной,
 
      она может отрицательно влиять на результаты и работу других
 
      процедур, которые вызывают ее. Крайне важно, чтобы процеду-
 


                                - 128 -
 
                           00152-01 97 08
 
 
      ра полностью  отвечала  требованиям  обязательных  разделов
 
      правил модульного программирования в системе  МОС  ВП  (см.
 
      приложение 1).
 
           Чтобы убедиться в модульности внутри процедур, следует
 
      выполнить, по крайней мере, проверки трех видов:
 
           1) тестирование отдельных блоков;
 
           2) проверку независимости от языка программирования;
 
           3) об'единенное тестирование.
 
 
 
           4.1. Тестирование отдельных блоков процедуры
 
 
           Перед тем, как об'единять блоки программ в новую  про-
 
      цедуру (например, в подпрограмму или внутреннюю процедуру),
 
      важно убедиться в том, что каждый такой блок работает неза-
 
      висимо. Тщательное тестирование блоков представляется  важ-
 
      ным по следующим причинам:
 
           - тестирование  небольших  блоков  уменьшает   уровень
 
      сложности в тестах;
 
           - проще и быстрее отладить небольшой  блок  программы,
 
      чем искать ошибку внутри нескольких блоков и в их интерфей-
 
      сах;
 
           - значительно проще станет последующий этап  об'едине-
 
      ния, если тщательно протестировать каждый отдельный блок  и
 
      устранить возникшие проблемы;
 
           - чем раньше при разработке  обнаружится  ошибка,  тем
 
      легче будет определить ее место.
 
           В тестировании блока существует три этапа:
 
           1) обзор целей разработки процедуры;
 
           2) выбор вариантов тестирования;
 
           3) прогон тестов.
 


                                - 129 -
 
                           00152-01 97 08
 
 
           Цели, преследуемые разработкой  процедуры,  выбираются
 
      на этапе требований/спецификаций. Данный этап не рассматри-
 
      вается в настоящем документе,  поскольку  он  несущественно
 
      влияет на модульность (разд. 1). Однако этот  этап  сущест-
 
      венно влияет на то, следует ли  признать  успешным  оконча-
 
      тельный продукт. Если продукт не  выполняет  ряда  операций
 
      или не соответствует требованиям, которые  были  выработаны
 
      на этапе требований/спецификаций, это неудавшийся  продукт.
 
      Должен быть, по крайней мере, один тест на  каждое  из  тех
 
      требований, которым в результате разработки должна удовлет-
 
      ворять процедура.
 
           Тесты, которыми пользуются, бывают двух видов:
 
           1) тесты для "черного ящика";
 
           2) тесты для "белого ящика".
 
           В тестах для "черного ящика" предполагается, что ниче-
 
      го не известно о внутренней работе  тестируемой  процедуры.
 
      Единственное, что интересует, -  это  выходная  информация,
 
      которая получается при заданных наборах входной информации.
 
           Тесты для "белого  ящика"  (которые  также  называются
 
      тестами для "прозрачного ящика") более  сложные,  поскольку
 
      они разрабатываются для прохода через определенные  участки
 
      программы или алгоритма внутри процедуры. В  них  предпола-
 
      гается, что известна внутренняя работа тестируемой процеду-
 
      ры, причем весьма подробно.
 


                                - 130 -
 
                           00152-01 97 08
 
 
           4.1.1. Тестирование "черного ящика"
 
 
           При проведении тестирования  "черного  ящика"  интерес
 
      представляют только результаты (выходная информация), кото-
 
      рые получаются при  конкретных  значениях  входных  данных.
 
      Просто повторяется выполнение процедуры  при  использовании
 
      входной информации из различных классов.  Наилучший  способ
 
      реализации этого заключается в написании командной процеду-
 
      ры для выполнения процедуры заданное число раз с  использо-
 
      ванием задаваемых тестовых данных [9].
 
           Процедуру пользователя следует выполнять для вариантов
 
      тестирования, которые  соответствуют  каждой  из  следующих
 
      категорий:
 
           1) ожидаемые входные данные -  это  значения,  которые
 
      предположительно процедура  будет  получать  в  большинстве
 
      вариантов своей работы;
 
           2) граничные значения - если предполагается, что вход-
 
      ное значение может быть в пределах от 1 до 999, используют-
 
      ся значения 1 и 999 в  качестве  вариантов  тестирования  с
 
      тем, чтобы убедиться, что в процедуре получаются  ожидаемые
 
      результаты в случае граничных значений;
 
           3) недопустимые значения - используя  предыдущий  при-
 
      мер, проверяется, что случится, если в процедуру в качестве
 
      входной информации поступит значение, которое меньше 1  или
 
      больше 999:
 
           - получит ли пользователь при этом полезное  сообщение
 
      об ошибке;
 
           - процедура просто остановится или попытается  исполь-
 
      зовать значения за пределами  своих  ограничений  и  выдаст
 
      неверный результат?
 


                                - 131 -
 
                           00152-01 97 08
 
 
      важно прогнать процедуру, используя  недопустимые  значения
 
      для того, чтобы получить ответы на поставленные вопросы.
 
           Рис.8 подытоживает способы тестирования "черного  ящи-
 
      ка".
 
               Способы тестирования "черного ящика"
 
 
                                  ----------------
                                  !              !
                                  !  Ожидаемая   !
                                  !              !
                                  !  входная     !
                                  !              !
                                 /!  информация  !
                                / !              !
                               /  ----------------
                              /
      ---------------        /
      !             !       /     ----------------
      !Тестирование !      /      !              !
      !             !     /       !  Граничные   !
      !"черного     !------------>!              !
      !             !     \       !  значения    !
      ! ящика"      !      \      !              !
      !             !       \     ----------------
      ---------------        \
                              \
                               \  ----------------
                                \ !              !
                                 \! Недопустимые !
                                  !              !
                                  ! значения     !
                                  !              !
                                  ----------------
 
                                Рис. 8
 
 
 
 
 
           4.1.2. Тестирование "белого ящика"
 
 
           При проведении тестирования "белого ящика"  в  отличие
 
      от тестирования "черного ящика" следует полностью представ-
 
      лять внутреннюю логику работы процедуры. Именно  внутреннюю
 
      работу, конкретные строки текста программы и тестируют этим
 
      способом.
 
           Тестирование "белого ящика" включает три этапа:


                                - 132 -
 
                           00152-01 97 08
 
 
           1) тестирование  каждой  структуры.  На  данном  этапе
 
      необходимо задать таKие наборы тестовых значений,  которыми
 
      бы обеспечивалось выполнение каждой структуры процедуры  по
 
      крайней мере один раз. Сюда входят все структуры - даже  те
 
      из них, которые выполняются только при необязательных пара-
 
      метрах и при указываемых пользователем параметрах, а  также
 
      подпрограммы, пользовательские программы развязки или конк-
 
      ретные программы обработки ошибок;
 
           2) тестирование каждой ветви алгоритма. На данном эта-
 
      пе цель заключается в обеспечении таких вариантов проверок,
 
      чтобы обязательно выполнялись по крайней мере один раз  все
 
      ветви алгоритма. В случае стандартной  логической  (булевс-
 
      кой) схемы алгоритма для этого, вообще говоря,  потребуется
 
      задать два значения, хотя это число может быть и большим  в
 
      случае составных или вложенных схем алгоритмов;
 
           3) тестирование каждого условия. Тестирование  условий
 
      связано с необходимостью написания таких вариантов  тестов,
 
      которыми обеспечивается получение всех  возможных  значений
 
      для каждого условия алгоритма по крайней мере раз и которы-
 
      ми каждая точка входа в программу или в подпрограмму  долж-
 
      на, по крайней мере  раз,  задействоваться  при  проведении
 
      тестирования. В случае составных или вложенных циклов долж-
 
      ны быть заданы многие варианты тестовых данных. При  тести-
 
      ровании точек входа нельзя забывать вызывать дополнительные
 
      подпрограммы (как внешние, так и внутренние), а также прог-
 
      раммы обработки ошибок. Если в процедуре имеется точка вхо-
 
      да JSB, такую точку входа также следует протестировать.
 
           Что при каждом виде тестирования "белого ящика"  отыс-
 
      киваются ошибки определенного типа. Например, при  тестиро-
 
      вании структур не обнаружится ошибка по отрицательному зна-


                                - 133 -
 
                           00152-01 97 08
 
 
      чению для случая, когда структура в качестве входной  вели-
 
      чины получает положительное  значение  в  тот  единственный
 
      раз, когда данная структура  выполняется.  Поэтому  следует
 
      выполнять все три вида тестирования "белого ящика".
 
           Рис.9 подытоживает способы тестирования  "белого  ящи-
 
      ка".
 
                 Способы тестирования "белого ящика"
 
 
                                   ------------------
                                   !                !
                                   ! Тестирование   !
                                   !                !
                                  /! структур       !
                                 / !                !
                                /  ------------------
                               /
      ----------------        /    ------------------
      !              !       /     !                !
      ! Тестирование !      /      ! Тестирование   !
      !              !     /       !                !
      ! "белого      !------------>! ветвей         !
      !              !     \       !                !
      !  ящика"      !      \      ! алгоритма      !
      !              !       \     !                !
      ----------------        \    ------------------
                               \
                                \  ------------------
                                 \ !                !
                                  \! Тестирование   !
                                   !                !
                                   ! условий        !
                                   !                !
                                   ------------------
 
                                Рис. 9
 
 
 
 
 
           4.2. Проверка    на    независимость     от     языков
 
      программирования
 
 
           Чтобы процедуры были максимально полезными, они должны
 
      иметь способность вызываться  программами,  написанными  на
 
      любых языках программирования. Обеспечение независимости от
 
      языка программирования является  важным  аспектом  создания


                                - 134 -
 
                           00152-01 97 08
 
 
      полезной процедуры.
 
           Проверка на независимость  от  языка  программирования
 
      является весьма  специфическим  видом  тестирования  блока.
 
      Этим  тестированием  проверяется  правильность   выполнения
 
      программы пользователя независимо от того, на  каком  языке
 
      программирования была написана вызывающая программа.
 
           Чтобы протестировать  процедуры  на  независимость  от
 
      языка программирования, пишется несколько управляющих прог-
 
      рамм на языках, которые  выбираются  произвольным  образом.
 
      Управляющая программа должна содержать только вызов  тести-
 
      руемой процедуры.
 
           Если в действительности окажется, что процедура  поль-
 
      зователя не независима  от  языка  программирования,  нужно
 
      убедиться в том, что она удовлетворяет следующим правилам:
 
           1) все неделимые данные должны передаваться  по  ссыл-
 
      кам, а все символьные строки - по дескрипторам.  Соблюдение
 
      данного правила является наиболее важным фактором  достиже-
 
      ния независимости от языка программирования;
 
           2)  не  допускается  использовать  операторы,  которые
 
      предполагают  среду  конкретного   языка   программирования
 
      (исполнительную систему). Например, оператор  ON  ERROR  GO
 
      BACK в процедуре на Бейсике  предполагает,  что  вызывающая
 
      программа написана также на Бейсике.
 
 
 
           4.3. Об'единенное тестирование
 
 
           Об'единенное тестирование  представляет  следующий  за
 
      тестированием блоков логический  шаг.  Тестирование  блоков
 
      направлено на проверку каждого отдельного компонента. Таким
 
      компонентом может  быть  модуль,  подпрограмма,  внутренняя
 


                                - 135 -
 
                           00152-01 97 08
 
 
      процедура (средство_имя) или конкретный внутренний  участок
 
      программы, который зависит от процедуры.  После  того,  как
 
      определено, что каждый блок работает  отдельно,  необходимо
 
      также оценить работоспособность блоков вместе в виде закон-
 
      ченной процедуры.
 
 
 
           4.3.1. Подход "все сразу" в об'единенном тестировании
 
 
           Об'единенное тестирование может быть  выполнено  одним
 
      из двух способов. Первый способ - это подход  "все  сразу".
 
      При данном способе об'единенного тестирования просто оформ-
 
      ляются все блоки, компонуются вместе  и  проверяется  сразу
 
      вся структура. Настоятельно рекомендуется  не  пользоваться
 
      данным способом, поскольку весьма трудно  определить  места
 
      нахождения ошибок. В качестве примера рассмотрим  организа-
 
      цию блоков процедуры, приведенной на  рис.10.  Предположим,
 
      что протестирована такая процедура с помощью  подхода  "все
 
      сразу" и обнаружена ошибка. Процедура просто  не  работает.
 
      Невозможно узнать, была ли ошибка в блоке а, блоке в, блоке
 
      с или блоке D.
 


                                - 136 -
 
                           00152-01 97 08
 
 
            Пример процедуры для об'единенного тестирования
 
 
                     -----------
                     !         !
                     ! Блок а  !         Уровень 1
                     !         !
                     -----------
                       /     \
                      /       \
                     /         \
      --------------/-----------\---------------------------
                   /             \
             ----------      ----------
             !        !      !        !
             ! Блок в !      ! Блок с !  Уровень 2
             !        !      !        !
             ----------      ----------
                                 !
      ---------------------------!--------------------------
                                 !
                                 !
                                 !
                             ----------
                             !        !
                             ! Блок D !  Уровень з
                             !        !
                             ----------
 
                               Рис. 10
 
 
 
 
           4.3.2. Подход    с    нарастанием    в    об'единенном
 
      тестировании
 
 
           Рекомендуемый для применения в об'единенном тестирова-
 
      нии подход  называется  тестированием  с  нарастанием.  При
 
      таком способе тестирования проверка процедуры начинается  с
 
      одного блока с достраиванием к нему по одному блоку  после-
 
      довательно. Прежде чем включать блок в об'единенное  тести-
 
      рование, его подвергают тщательному тестированию на  уровне
 
      блока.
 
           Об'единенное тестирование с нарастанием сложности ока-
 
      зывается особенно  удобным  средством  отыскания  следующих
 
      видов ошибок:
 


                                - 137 -
 
                           00152-01 97 08
 
 
           - проблемы с интерфейсом вызова между блоками  (напри-
 
      мер, несоответствие порядка параметров в вызывающем и вызы-
 
      ваемом блоках);
 
           - неверные допущения относительно того, какие значения
 
      возвращаются и каким блокам;
 
           - непредусмотренная передача управления между блоками.
 
           Если воспользоваться для иллюстрации примером процеду-
 
      ры (см. Рис.10), то следовало бы сначала выполнить тестиро-
 
      вание блока а на уровне 1 прежде, чем перейти к  уровню  2,
 
      где следует протестировать комбинацию блоков а и в. На каж-
 
      дом уровне следует сначала исправить обнаруженные ошибки, а
 
      затем переходить к следующему уровню. После завEршения пос-
 
      леднего шага, протестировав блоки а, в, с и D, пользователь
 
      знает, что полностью процедура работает верно.
 
           Поскольку тестирование было  начато  с  верхней  части
 
      процедуры и блоки добавлялись последовательно с более  низ-
 
      ких уровней, можно говорить об использовании подхода  свер-
 
      ху-вниз в об'единенном тестировании. Можно  было  столь  же
 
      просто начать с третьего уровня и использовать так называе-
 
      мый подход снизу-вверх.
 
           Как нетрудно видеть из примера (см.  Рис.10),  имеется
 
      ряд ощутимых преимуществ при  об'единенном  тестировании  с
 
      нарастанием:
 
           - нет необходимости ожидать завершения разработки про-
 
      цедуры для того, чтобы начать ее об'единенное тестирование;
 
           - при тестировании с нарастанием  упрощается  отладка,
 
      поскольку модули и интерфейсы  можно  тестировать  по  мере
 
      роста системы;
 
           - ошибки программирования интерфейсов и неверные допу-
 
      щения между блоками обнаруживаются на ранней стадии;


                                - 138 -
 
                           00152-01 97 08
 
 
           - поскольку ранее проверенные блоки  проверяются  пов-
 
      торно по мере добавления новых блоков, вероятность  обнару-
 
      жения менее очевидных ошибок значительно возрастает.
 
 
 
           4.4. Тестирование на реентерабельность
 
 
           Важно протестировать процедуры на повторную входимость
 
      (реентерабельность) до того, как помещать их в библиотечные
 
      средства. Поскольку асинхронные системные прерывания  могут
 
      возникать в произвольный момент времени, процедуры, которые
 
      не являются реентерабельными по AST, могут вести себя  неп-
 
      редсказуемым образом. В  частности,  асинхронное  системное
 
      прерывание, которое возникает в момент выполнения  процеду-
 
      рой операции по изменению содержимого ячеек памяти  в  слу-
 
      чае, когда такая процедура не является  реентерабельной  по
 
      AST, может испортить содержимое ячеек памяти такой процеду-
 
      ры (см. Подраздел 3.3).
 
           Обеспечение полной реентерабельности  является  важным
 
      моментом в среде с многоцепочечными задачами,  например,  в
 
      среде, возникающей при программировании на языке АДА.
 
 
 
           4.4.1. Проверка реентерабельности по AST
 
 
           Существует два способа проверки процедуры на повторную
 
      входимость с точки зрения обработки  асинхронных  системных
 
      прерываний:
 
           1) использовать символический отладчик;
 
           2) произвести вручную проверку за столом.
 


                                - 139 -
 
                           00152-01 97 08
 
 
           4.4.1.1. Проверка реентерабельности по AST  с  помощью
 
      отладчика
 
 
           Для проверки повторной входимости с точки зрения обра-
 
      ботки асинхронных системных прерываний с помощью  отладчика
 
      необходимо осуществить пять шагов [10]:
 
           1) активизировать процедуру (первая цепочка);
 
           2)  установить  контрольные  точки  по  всей   памяти,
 
      используемой процедурой;
 
           3) сделать  вторую  активизацию  процедуры  с  помощью
 
      команды CALL и дать ей  возможность  проработать  до  конца
 
      (вторая активизация соответствует цепочке уровня  асинхрон-
 
      ных системных прерываний). Проверить,  что  цепочка  уровня
 
      асинхронных системных прерываний при своей работе не  изме-
 
      няет информацию в памяти, к которой  имеет  доступ  цепочка
 
      первой активизации процедуры. Если же цепочка уровня асинх-
 
      ронных системных прерываний все же изменяет какую то ячейку
 
      памяти, проверить, что это не является причиной возникнове-
 
      ния каких-либо нежелательных  побочных  эффектов  в  первой
 
      цепочке;
 
           4) продвинуться на одну команду в первой активизации;
 
           5) повторить шаги 3 и 4 до конца процедуры с использо-
 
      ванием первой активизации.
 
 
 
           4.4.1.2. Проверка реентерабельности по AST вручную
 
 
           Реализация проверки реентерабельности по  AST  вручную
 
      состоит из следующих четырех шагов:
 
           1) создать активизацию тестируемой процедуры и ее дан-
 
      ных с помощью стандартных средств отслеживания работы  про-
 
      цедуры вручную;


                                - 140 -
 
                           00152-01 97 08
 
 
           2) создать вторую активизацию процедуры с помощью того
 
      же процесса. Эта активизация  представляет  цепочку  уровня
 
      асинхронных системных прерываний. Проследить ход выполнения
 
      цепочки уровня асинхронных системных прерываний до заверше-
 
      ния, по одному оператору за один раз. Не  следует  забывать
 
      изменять содержимое всех ячеек памяти и переменных для каж-
 
      дой инструкции процедуры.  Проверить,  что  цепочка  уровня
 
      асинхронных системных прерываний  при  работе  не  изменяет
 
      содержимое ячеек памяти,  к  которым  имеет  доступ  первая
 
      цепочка. Если цепочка уровня асинхронных системных прерыва-
 
      ний все же изменяет содержимое  какой-либо  ячейки  памяти,
 
      проверить, не возникают ли при этом какие-либо  нежелатель-
 
      ные эффекты для работы первой цепочки;
 
           3) продвинуться на одну структуру первой  цепочки,  не
 
      забыв при этом скорректировать содержимое ячеек памяти;
 
           4) повторить шаги 2 и 3, пока по шагам не будут  прой-
 
      дены все структуры новой  цепочки  (следует  отметить,  что
 
      каждая структура цепочки уровня асинхронных системных  пре-
 
      рываний выполняется пошагово полностью при каждом  выполне-
 
      нии шага 2).
 
           Как нетрудно видеть, такое тестирование - это проверка
 
      между выполнением каждых двух структур процедуры.  Наиболь-
 
      шую трудоемкость тестирования за  столом  на  реентерабель-
 
      ность по AST  представляет  пошаговая  проверка  процедуры,
 
      написанной на языке ассемблера, и проверка  между  выполне-
 
      нием каждой инструкции ассемблера.
 


                                - 141 -
 
                           00152-01 97 08
 
 
           4.4.2. Проверка полной реентерабельности
 
 
           Полная реентерабельность отличается  от  реентерабель-
 
      ности по AST числом выполняемых цепочек. Для проверки реен-
 
      терабельности по AST можно поддерживать работу только  двух
 
      цепочек: цепочки уровня асинхронных системных прерываний  и
 
      обычной цепочки. Полная реентерабельность важна в тех  сре-
 
      дах, где можно поддерживать выполнение  множества  цепочек,
 
      например, в среде программ, написанных на языке АДА.
 
           Процедура полностью  реентерабельна,  если  при  любом
 
      числе выполняемых цепочек каждая их них  может  проработать
 
      до своего завершения, не влияя ни на одну другую  выполняе-
 
      мую цепочку.
 
           Вообще говоря, процедура,  которая  является  повторно
 
      входимой с точки  зрения  обработки  асинхронных  системных
 
      прерываний, является также полностью реентерабельной.
 
 
 
           4.5. Анализ производительности
 
 
           Все процедуры  обслуживания  таймера  и  распределения
 
      ресурсов должны собирать статистику  для  возможной  оценки
 
      производительности и  отладки.  В  процедурах  обслуживания
 
      таймера и распределения ресурсов должны быть запрограммиро-
 
      ваны следующие две точки входа:
 
      LIB_SHOW_имя
 
      LIB_STAT_имя
 


                                - 142 -
 
                           00152-01 97 08
 
 
           4.5.1. Входная точка SHOW
 
 
           Через входую точку SHOW  получаются  отформатированные
 
      цепочки символов (строки), содержащие необходимую  информа-
 
      цию. Вызывающая последовательность для входной  точки  SHOW
 
      имеет вид:
 
      LIB_SHOW_имя[код[,пользовательская_программа_развязки-
 
                         [,параметр_пользователя]]]
 
           Код - необязательный код (вида LIB_K_код),  обозначаю-
 
      щий необходимую статистическую информацию. Для каждой  ста-
 
      тистической характеристики определяется отдельный код; коды
 
      должны совпадать для точек  SHOW  и  STAT.  Соответствующие
 
      кодам значения для каждой процедуры начинаются с единицы. В
 
      документации по процедуре в разделе,  посвященном  функцио-
 
      нальному назначению, должны быть  перечислены  используемые
 
      коды. Если параметр "код" опущен либо равен нулю, процедура
 
      выдает всю статистическую информацию.
 
           Пользовательская_программа_развязки - адрес  пользова-
 
      тельской программы развязки (необязательный параметр). Если
 
      данный  параметр  опущен,   статистические   характеристики
 
      выдаются на SYS$OUTPUT.
 
           Параметр_пользователя - необязательный параметр  поль-
 
      зователя,  который  должен  быть  передан  пользовательской
 
      программе развязки. Если данный параметр опущен,  пользова-
 
      тельской программе развязки передается укороченный  список.
 
      При наличии данного  параметра  он  копируется  в  перечень
 
      параметров, передаваемых пользовательской программе развяз-
 
      ки. Таким образом,  32-х  разрядная  входная  точка  списка
 
      параметров, переданная вызывающей программой, копируется во
 
      входную точку списка  параметров,  передаваемого  пользова-
 


                                - 143 -
 
                           00152-01 97 08
 
 
      тельской программе развязки.  Следовательно,  тип  доступа,
 
      тип данных, форма параметра и механизм передачи могут  быть
 
      произвольными, соответствующими соглашению между вызывающей
 
      программой и пользовательской программой развязки.
 
           Необязательная  пользовательская  программа   развязки
 
      должна иметь вид (см. П. 3.1.6.):
 
      ACTION-ROUTINE (цепочка_символов [,параметр_пользователя])
 
 
 
           4.5.2. Входная точка STAT
 
 
           Процедура STAT выдает необходимую информацию в  двоич-
 
      ном виде. Вызывающая последовательность имеет вид:
 
      LIB_STAT_имя (код, значение)
 
           Код - код, указывающий требуемую статистическую харак-
 
      теристику. Для каждой статистической характеристики задает-
 
      ся отдельный код; коды те же самые, что и для  точек  SHOW.
 
      Коды начинаются с единицы.
 
           Значение - это  значение  возвращаемой  статистической
 
      характеристики.
 
 
 
           4.6. Управляющие процедуры исполнительной библиотеки
 
 
           Для управления временем и ресурсами  в  исполнительной
 
      библиотеке имеется ряд процедур [1]:
 
           1) LIB$SHOW_VM - является процедурой управления ресур-
 
      сом,  которая  возвращает  статистические   характеристики,
 
      накопленные в  результате  вызовов  процедур  LIB$GET_VM  и
 
      LIB$FREE_VM. По умолчанию возвращается  информация  в  виде
 
      Tрех статистических характеристик:
 
           - количество успешно выполненных вызовов LIB$GET_VM;
 
           - количество успешных вызовов LIB$FREE_VM;


                                - 144 -
 
                           00152-01 97 08
 
 
           - количестов байтов, распределенных LIB$GET_VM, но еще
 
      не освобожденных LIB$FREE_VM.
 
      Процедура LIB$SHOW_VM возвращает эти статистические  харак-
 
      теристики в отформатированном виде: NNNN;
 
           2) LIB$STAT_VM - процедура управления ресурсом,  кото-
 
      рая возвращает вызывающей программе одну из трех  статисти-
 
      ческих  характеристик,  получаемую  в  результате   вызовов
 
      LIB$GET_VM и LIB$FREE_VM. Это те же статистические характе-
 
      ристики, которые  возвращаются  процедурой  LIB$SHOW_VM.  В
 
      отличие  от  LIB$SHOW_VM,  которая  выдает   статистические
 
      характеристики в отформатированном виде на SYS$OUTPUT, про-
 
      цедура  LIB$STAT_VM  возвращает  указанную   статистическую
 
      характеристику в виде целого числа со  знаком,  занимающего
 
      длинное слово;
 
           3) LIB$SHOW_TIMER  -  процедура  управления  временем,
 
      которая возвращает отсчеты времени  и  значения  счетчиков,
 
      накопленные с момента предыдущего вызова LIB$INIT_TIMER,  и
 
      отображает эту информацию на SYS$OUTPUT. С помощью  пользо-
 
      вательской программы  развязки  можно  видоизменить  такое,
 
      реализуемое по умолчанию, поведение процедуры. По умолчанию
 
      получаемая  информация  представляет  пять   статистических
 
      характеристик:
 
           - истекшее реальное время;
 
           - истекшее время использования центрального  процессо-
 
      ра;
 
           - счетчик буферированных операций обмена;
 
           - счетчик операций обмена с прямым доступом;
 
           - счетчик страничных отказов;
 
           4) LIB$STAT_TIMER  -  процедура  управления  временем,
 
      которая  возвращает  ту  же  информацию,  что  и  процедура


                                - 145 -
 
                           00152-01 97 08
 
 
      LIB$SHOW_TIMER. Oтличие заключается в  том,  что  процедура
 
      LIB$STAT_TIMER возвращает информацию в виде длинного  слова
 
      или квадрослова без знака, тогда  как  процедура  LIB$SHOW_
 
      TIMER возвращает информацию  в  формате  HHHH:MM:SS:CC  для
 
      отсчетов времени и формате  NNNN  для  значений  счетчиков.
 
      Кроме того, за один вызов процедура LIB$STAT_TIMER  возвра-
 
      щает только одну из пяти доступных статистических  характе-
 
      ристик.
 
 
 
 
                            5. Oб'единение
 
 
 
           5.1. Группирование процедур
 
 
           Библиотеки модульных процедур содержат  скомпилирован-
 
      ные или ассемблированные об'ектные программы, которые пред-
 
      назначены для соединения с вызывающей программой  на  этапе
 
      компоновки. Ссылки на процедуры из таких  библиотек  разре-
 
      шаются (реализуются) в момент просмотра компоновщиком поль-
 
      зовательских библиотек,  указанных  в  команде  LINK,  либо
 
      просмотра используемых по  умолчанию  системных  библиотек.
 
      Затем при прогоне  программа  может  вызывать  библиотечные
 
      процедуры.
 
           Некоторые поставляемые библиотечные процедуры,  напри-
 
      мер, общая исполнительная библиотека процедур  системы  мос
 
      вп (которая  также  называется  исполнительной  библиотекой
 
      процедур),  обеспечивают  работу  компонентов  операционной
 
      системы МОС ВП. Для часто выполняемых операций можно  явным
 
      образом осуществлять  доступ  к  процедурам  исполнительной
 
      библиотеки. Для этого достаточно включить  вызов  процедуры
 
      исполнительной библиотеки  в  свою  программу.  Компоновщик


                                - 146 -
 
                           00152-01 97 08
 
 
      автоматически осуществит поиск по используемым по умолчанию
 
      библиотекам для разрешения ссылок к процедурам исполнитель-
 
      ной библиотеки процедур [1].
 
           Можно создать библиотеки собственных процедур и разде-
 
      ляемые образы, если воспользоваться  основными  положениями
 
      по данным вопросам  (пп.  5.1.2,  5.2.1).  Перед  тем,  как
 
      начать группировать модульные процедуры, надо  убедиться  в
 
      том, что они соответствуют правилам, перечисленным в прило-
 
      жении 1.
 
           Существует три способа группировки модульных процедур:
 
           1) об'единение об'ектных модулей в библиотеку  об'ект-
 
      ных модулей;
 
           2) компоновка об'ектных модулей вместе  в  разделяемый
 
      образ;
 
           3) об'единение разделяемых образов в библиотеку разде-
 
      ляемых образов.
 
 
 
           5.1.1. Создание префиксов средств
 
 
           Префикс средства - это идентификатор группы  для  ряда
 
      взаимосвязанных  процедур,  содержащихся   в   библиотечном
 
      средстве. Префикс средства присутствует в имени каждой про-
 
      цедуры, находящейся в таком библиотечном средстве. Примером
 
      библиотечного средства может служить средство  обслуживания
 
      экрана. Имена всех процедур, входящих в средство обслужива-
 
      ния экрана, начинаются с SMG, например, SMG$ERASE_CHARS.
 
           Чтобы создать собственный префикс средства, необходимо
 
      выполнить следующие действия:
 
           1)  выбрать  префикс  средства.  Такой  префикс  может
 
      содержать от одного до 27 символов. Вместе с тем,  рекомен-
 


                                - 147 -
 
                           00152-01 97 08
 
 
      дуется, чтобы префиксы средств содержали от 2 до  4  симво-
 
      лов;
 
           2) если средство будет  порождать  сообщения,  следует
 
      задать уникальный номер средства в исходном  файле  сообще-
 
      ний. Это число может быть в пределах от 0  до  4095.  Любое
 
      число из данного диапазона, которое не используется  кем-то
 
      другим в системе, является приемлимым. Такой номер средства
 
      будет использоваться обслуживающей программой выдачи  сооб-
 
      щений при генерации значения исключительного состояния  для
 
      данного сообщения. Бит 27 (STS$V_CUST_DEF) значения  исклю-
 
      чительного состояния указывает, кем было задано это  значе-
 
      ние: пользователем или поставщиком. Данный бит должен  быть
 
      равен 1, если номер средства создан пользователем [8];
 
           3) префикс средства следует использовать при  наимено-
 
      вании   всех   процедур   из   этого    нового    средства
 
      (см. П. 3.1.2).
 
 
 
           5.1.2. Создание библиотек об'ектных модулей
 
 
           В дополнение к применению системных библиотек  об'ект-
 
      ных модулей, которые используются по умолчанию, можно также
 
      создавать собственные библиотеки об'ектных модулей.  Созда-
 
      ваемая библиотека об'ектных модулей может содержать об'ект-
 
      ные файлы, порожденные любым из компиляторов  языков  прог-
 
      раммирования системы МОС ВП.
 
           Для создания библиотеки об'ектных  модулей  необходимы
 
      следующие действия:
 
           1) написать или собрать те  процедуры,  которые  жела-

      тельно сгруппировать вместе в библиотеку об'ектных модулей.
 
      Убедиться в том, что выбранные для модулей, процедур и пре-
 


                                - 148 -
 
                           00152-01 97 08
 
 
      фиксов средств имена соответствуют основным положениям (см.
 
      п. 3.1.2);
 
           2)  скомпилировать  исходные  тексты   для   получения
 
      об'ектных файлов тех процедур, которые должны быть помещены
 
      в библиотеку;
 
           3) создать  библиотеку  об'ектных  модулей  с  помощью
 
      команды LIBRARY:
 
      $ LIBRARY/CREATE имя_библиотеки.OLB спецификация_фай-
 
      _$ла1.OBJ [,спецификация_файла2.OBJ [,...]]
 
           Параметр "имя_библиотеки" - это присвоенное библиотеке
 
      имя.   По   умолчанию   расширение    имени    файла    для
 
      "имени_библиотеки" будет OLB.
 
           Параметры "спецификация_файла" - это  об'ектные  файлы
 
      процедур, которые желательно включить в библиотеку  об'ект-
 
      ных модулей. По умолчанию расширением "спецификации  файла"
 
      будет OBJ.
 
           Данный процесс рассмотрен на примере создания  библио-
 
      теки об'ектных модулей.
 
           Пример.
 
           Первый шаг - выбор тех процедур, которые будут  содер-
 
      жаться в создаваемой библиотеке. Пусть создаваемая  библио-
 
      тека  называется  CRAPHICS.OLB.  Данная  библиотека   будет
 
      содержать  модульные  процедуры   создания   математических
 
      представлений окружностей,  цилиндров,  площадей  и  прочих
 
      геометрических об'ектов.
 
           Используемые  файлы - это GRASPHERE.BAS и GRACUBE.FOR.
 
      В GRACUBE.FOR содержится одна процедура GRA_CUBE для  гене-
 
      рации формы куба (GRA - префикс  создаваемого  средства,  а
 
      символ подчеркивания в имени процедуры указывает на то, что
 
      это - разработанная пользователем процедура). GRASPHERE.BAS


                                - 149 -
 
                           00152-01 97 08
 
 
      содержит ряд процедур, которые сгруппированы  вместе,  пос-
 
      кольку они совместно используют близкие по смыслу и  назна-
 
      чению  подпрограммы.  Содержащиеся  в  GRASPHERE  процедуры
 
      порождают сферы (GRA_SPHERE),  сжатые  эллипсоиды  вращения
 
      (GRA_OBL_SPH) и элементы сферических тел вращения  (GRA_SPH
 
      _SEC).
 
           После того, как были выбраны и  правильно  наименованы
 
      процедуры, перейдем ко второму шагу  и  создадим  об'ектные
 
      файлы, которые необходимы для построения библиотеки об'ект-
 
      ных модулей. Команды, используемые для  создания  об'ектных
 
      файлов, следующие:
 
           $ BASIC CRASPHERE.BAS
 
           $ FORTRAN GRACUBE.FOR
 
           Получаем об'ектные файлы GRASPHERE.OBJ и GRACUBE.OBJ.
 
           Заключительный шаг  -  создать  собственно  библиотеку
 
      об'ектных модулей из таких об'ектных файлов. Создадим  биб-
 
      лиотеку об'ектных модулей, выдав команду:
 
           $ LIBRARY /CREATE GRAPHICS GRASPHERE,GRACUBE
 
      отметим, что не были заданы расширения  имен  файлов,  пос-
 
      кольку использовались только принимаемые по умолчанию  зна-
 
      чения.
 
           После того как была выдана команда LIBRARY, библиотека
 
      об'ектных модулей GRAPHICS.OLB готова к процедуре компонов-
 
      ки с прикладной программой (подраздел 5.3).
 


                                - 150 -
 
                           00152-01 97 08
 
 
           5.2. Разделяемые библиотечные образы
 
 
           Если имеется набор процедур,  которые,  как  предпола-
 
      гается, будут использоваться некоторым  числом  пользовате-
 
      лей, может потребоваться сгруппировать  такие  процедуры  в
 
      образ разделяемой библиотеки, кратко называемые разделяемым
 
      образом. Такой образ аналогичен библиотеке об'ектных  моду-
 
      лей за тем лишь отличием, что он был предварительно скомпо-
 
      нован с тем, чтобы  все  ссылки  между  процедурами  внутри
 
      такой библиотеки были уже разрешены.
 
           Образ разделяемой библиотеки обладает следующими преи-
 
      муществами:
 
           - экономит пространство  памяти.  Несколько  процессов
 
      могут совместно использовать (разделять) одну копию  разде-
 
      ляемого образа вместо того, чтобы каждый процесс  отыскивал
 
      собственную копию на диске;
 
           - экономит дисковую память. Программы,  скомпонованные
 
      с образом разделяемой библиотеки, совместно используют одну
 
      копию библиотеки на диске, а не включают ее в  свой  выпол-
 
      няемый образ;
 
           - сокращает  время  компоновки.  Поскольку  внутренние
 
      ссылки в библиотеке уже  разрешены,  компоновщику  остается
 
      меньше работы;
 
           - позволяет вносить изменения без повторной  компонов-
 
      ки. Можно создать новую версию образа разделяемой библиоте-
 
      ки, которая автоматически будет использоваться всеми  прог-
 
      раммами, скомпонованными с ней. При этом  пользователям  не
 
      требуется перекомпоновывать свои программы.
 
           Наиболее важное преимущество использования образа раз-
 
      деляемой библиотеки  заключается  в  возможности  экономить
 


                                - 151 -
 
                           00152-01 97 08
 
 
      физическую память за счет совместного  использования  одной
 
      копии в памяти кода библиотеки всеми  пользователями.  Воз-
 
      можность создания такого образа предосталяется привилегиро-
 
      ванным пользователям, обычно администратору системы,  кото-
 
      рый с помощью обслуживающей программы  устанавливает  образ
 
      разделяемой библиотеки с атрибутом /SHAREABLE. Это  преиму-
 
      щество не ограничивается только образами  разделяемых  биб-
 
      лиотек. Любой выполняемый образ можно установить как разде-
 
      ляемый (совместно используемый) [11].
 
 
 
           5.2.1. Создание образов разделяемых библиотек
 
 
           Для создания образа разделяемой библиотеки  достаточно
 
      просто взять набор процедур  и  скомпоновать  их  вместе  в
 
      образ разделяемой библиотеки.  Дополнительно  к  процедурам
 
      пользователю необходимо обеспечить вектор передачи  и  файл
 
      необязательных параметров компоновщика.
 
           Рис. 11  дает  обзор  процесса  создания  разделяемого
 
      образA (на примере из п. 5.1.2).
 


                                - 152 -
 
                           00152-01 97 08
 
 
                 Создание разделяемого образа
 
                           ----------      ----------
                           !        !      !        !
                           !    1   !      !    2   !
                           !        !      !        !
                           ----------      ----------
                                !  ---------!   !
                                !  !            !
                                V  V            V
                           ----------      ----------
                           !        !      !        !
                -----------!    4   !<-----!    3   !
                !          !        !      !        !
                !          ----------      ----------
                !              !
                !              !
                V              V
           ----------      ----------
           !        !      !        !
           !    5   !      !    6   !
           !        !      !        !
           ----------      ----------
 
 
 
      1 - созданная пользователем библиотека об'ектных
      модулей (GRAPHICS.OLB ).
      2 - командная процедура, содержащая команду $LINK
      (MAKESHAR.COM).
      3 - файл для управления функциональными возможностями
      (необязательный): распределение памяти, универсаль-
      ные идентификаторы (MAKESHAR.OPT).
      4 - компоновщик;
      5 - листинг (GRAPHICS.MAP).
      6 - созданный пользователем разделяемый образ
      (CRAPHICS EXE).
 
 
                               Рис. 11
 
 
 
           5.2.2. Создание вектора передачи
 
 
           При компоновке программы с образом разделяемой библио-
 
      теки программа-компоновщик помещает в  тело  прогрAммы  два
 
      информационных об'екта для каждой ссылки к подпрограмме  из
 
      такого образа:
 
           1) имя разделяемого образа;
 
           2) местоположение точки входа подпрограммы относитель-
 
      но начала разделяемого образа.


                                - 153 -
 
                           00152-01 97 08
 
 
           Поскольку используется относительная адресация,  подп-
 
      рограмма не может изменить своего местоположения в  образе,
 
      не сделав неработоспособными все  использующие  ее  образы.
 
      Использование вектора передачи позволяет изменять  подпрог-
 
      раммы и реорганизовать их, не влияя на ранее скомпонованные
 
      программы.
 
           Вектор передачи - это модуль, содержащий список  "нап-
 
      равляющих адресов" для подпрограмм из разделяемого  образа,
 
      который помещается в начале образа. При использовании  век-
 
      тора передачи, программы, компонуемые с  разделяемым  обра-
 
      зом, привязываются к точкам входа, содержащимся  в  векторе
 
      передачи, а не к реальным подпрограммам. Затем через  точку
 
      входа такого вектора управление передается  реальной  подп-
 
      рограмме. Поскольку каждая  точка  входа  в  таком  векторе
 
      занимает одинаковый об'ем,  сравнительно  просто  сохранить
 
      при всех изменениях образа относительное расположение точки
 
      входа.
 
           Вектор передачи следует создавать на языке  ассемблера
 
      СМ 1700, но для этого вовсе не требуется знать  этот  язык.
 
      Можно воспользоваться шаблоном для вектора передачи:
 
      ;+
 
      ; шаблон на Макроассемблере для вектора
 
      ; передачи.
 
      ;
 
      ; в Макроассемблере комментарии начинаются
 
      ; символом "точка с запятой".
 
      ; пробелы и символы табуляции могут присутствовать
 
      ; поочередно всюду, где указан пробел.
 
      ; -
 
 


                                - 154 -
 
                           00152-01 97 08
 
 
      ; +
 
      ; следующими двумя строками задается имя модуля, которое
 
      ; в данном примере GRA_VECTOR (вектор для GRA_средство), и
 
      ; идентификация (версия) данного модуля, которая здесь
 
      ; 1-001. Замените GRA_VECTOR любым выбранным именем модуля.
 
      ; -
 
              TITLE GRA_VECTOR
 
              IDENT /1-001/
 
      ; +
 
      ; Cледующими строками описывается Макроопределение,
 
      ; названное ROUTINE, которое при Макровызове порождает
 
      ; одну точку входа вектора передачи. Введите данные
 
      ; строки точно так, как указано: никаких подстроек их
 
      ; производить не требуется.
 
      ; -
 
              .MACRO .ROUTINE NAME
 
              .EXTRN          NAME
 
              .ALIGN  QUAD
 
              .TRANSFER       NAME
 
              .MASK           NAME
 
              JMP             NAME+2
 
              .ENDM
 
      ; +
 
      ; следующими двумя строками определяется та программная
 
      ; секция (PSECT), в которой будет резидентен вектор
 
      ; передачи. Здесь единственное, что можно изменить,
 
      ;  - имя программной секции (PSECT), которое в данном
 
      ; случае $$$$VECTOR. При изменении этого имени убедитесь
 
      ; в том, что оно расположено впереди всех других имен
 
      ; программных секций образа разделяемой библиотеки.


                                - 155 -
 
                           00152-01 97 08
 
 
      ; использование здесь денежных знаков, что обычно ограни-
 
      ; чивается программным обеспечением разработчиков МОС ВП,
 
      ; необходимо, поскольку денежный знак при символьном упоря-
 
      ; дочении имен оказывается раньше любого другого допустимо-
 
      ; го в идентификаторе символа. Такое имя не может совпадать
 
      ; с именами программного обеспечения разработчика, поэтому
 
      ; нет никакой опасности в использовании знаков денежной
 
      ; единицы. Остальные две строки определяют атрибуты програм
 
      ; мной секции, которые нельзя изменить.
 
      ; -
 
              .PSECT $$$$VEKTOR PIC, USR, CON, REL, LCL, SHR,-
 
                                EXE, RD, NOWRT, QUAD
 
      ; +
 
      ; за данным местом следуют описания элементов вектора.
 
      ; каждый элемент задается строкой вида:
 
      ;        ROUTINE имя_подпрограммы,
 
      ; где имя-подпрограммы - это имя той подпрограммы, для
 
      ; которой желательно создать точку входа. Порядок, в
 
      ; котором перечисляются подпрограммы, не существенен,
 
      ; но важно, чтобы не изменялся порядок, в котором
 
      ; впервые был создан образ разделяемой библиотеки.
 
      ; если желательно добавить подпрограммы, добавляйте их
 
      ; в конец списка. В целях сохранения совместимости ни
 
      ; в коем случае нельзя удалять подпрограммы.
 
      ;
 
      ; в качестве примера приведены описания точек входа
 
      ; для подпрограмм GRA_SPHERE, GRA_OBL_SPH и
 
      ; GRA_SPH_SEC. Замените их своими точками входа:
 
      ; -
 
              ROUTINE GRA_SPHERE


                                - 156 -
 
                           00152-01 97 08
 
 
              ROUTINE GRA_OBL_SPH
 
              ROUTINE GRA_SPH_SEC
 
      ; +
 
      ; последняя строка обозначает конец модуля.
 
      ; -
 
              .END
 
           Чтобы использовать данный шаблон для создания  вектора
 
      передачи, нужно выполнить следующие действия:
 
           1) создать файл типа MAR, содержащий шаблон. Желатель-
 
      но в качестве имени такого файла использовать  имя  модуля.
 
      Поэтому, если воспользоваться именем модуля,  указанного  в
 
      шаблоне _GRA_VECTOR, имя файла будет GRA_VECTOR.MAR;
 
           2) воспользоваться указаниями, содержащимися в шаблоне
 
      и отредактировать файл так, чтобы получить правильный  век-
 
      тор для своего средства;
 
           3) оттранслировать модуль вектора:
 
                $MACRO GRA_VECTOR     .
 
 
 
           5.2.3. Создание   файла   необязательных    параметров
 
      компоновщика
 
 
           Файл необязательных параметров  компоновщика  содержит
 
      команды компоновщику относительно  того,  как  ему  следует
 
      построить выполняемый или разделяемый образ. Файл  необяза-
 
      тельных параметров редко используется для выполняемых обра-
 
      зов,  поскольку  используемые  компоновщиком  параметры  по
 
      умолчанию оказываются вполне достаточными. Однако для  раз-
 
      деляемых образов требуется дополнительная информация, кото-
 
      рую можно указать только  с  помощью  файла  необязательных
 
      параметров [7].
 


                                - 157 -
 
                           00152-01 97 08
 
 
           В файле необязательных параметров  компоновщика  можно
 
      задать много различных атрибутов образа, но только  неболь-
 
      шое число из них обычно требуется для  образов  разделяемых
 
      библиотек. В данном пункте содержится шаблон файла необяза-
 
      тельных параметров  компоновщика,  где  кратко  описывается
 
      каждый используемый необязательный параметр. Чтобы  приспо-
 
      собить  файл  необязательных  параметров  компоновщика  под
 
      собственные нужды, необходимо следовать инструкциям, содер-
 
      жащимся в  комментариях  файла  необязательных  параметров.
 
      Предлагается в качестве имени  файла  использовать  префикс
 
      средства, за которым будет следовать "_OPTIONS", а тип фай-
 
      ла OPT. Поэтому, например, для средства GRA имя файла  нео-
 
      бязательных параметров будет GRA_OPTIONS.OPT.
 
           Шаблон файла  необязательных  параметров  компоновщика
 
      следующий:
 
 
 
      ! +
 
      ! в файле необязательных параметров компоновщика
 
      ! комментарии начинаются с восклицательного знака.
 
      ! пробелы и знаки табуляции могут присутствовать
 
      ! поочередно всюду, где показан пробел.
 
      ! -
 
 
 
      ! +
 
      ! первыми строками задается имя разделяемого образа.
 
      ! в данном примере в качестве имени используется
 
      ! GRA_SHR (разделяемый образ для средства GRA).
 
      ! замените GRA_SHR именем своего разделяемого образа.
 
      !
 
      ! если не задать имени образа, компоновщик воспользу-


                                - 158 -
 
                           00152-01 97 08
 
 
      ! ется именем первого входного файла.
 
      ! -
 
 
 
      NAME = GRA_SHR
 
 
 
      ! +
 
      ! следующей строкой задается цепочка символов иденти-
 
      ! фикации. Цепочка идентификации - это номер версии
 
      ! разделяемого образа. Замените "V1.0" цепочкой
 
      ! идентификации своего разделяемого образа.
 
      !
 
      ! (можно позже вывести на экран такую цепочку идентифи-
 
      ! кации с помощью команды ANALYZE/IMAGE.)
 
      ! -
 
 
 
      IDENTIFICATION = "V1.0"
 
 
 
      ! +
 
      ! следующей строкой задается критерий соответствия и
 
      ! идентификация глобальной секции.
 
      !
 
      ! в данном примере в качестве критерия соответствия
 
      ! глобальной секции используется "LEQUAL"(меньше либо
 
      ! равно). В своем файле необязательных параметров для
 
      ! компоновщика также следует использовать "LEQUAL".
 
      !
 
      ! значения идентификации старшей и младшей глобальной
 
      ! секции - "1,1". Первая "1" - это старшее значение
 
      ! идентификации. Не изменяйте этого числа. Вторая "1"
 
      ! - это младшее значение идентификации. Увеличивайте


                                - 159 -
 
                           00152-01 97 08
 
 
      ! на единицу младшее значение идентификации при
 
      ! очередном добавлении точек входа в вектор передачи.
 
      ! не изменяйте этого значения, если только не
 
      ! изменяется программа, но не добавляются новые точки.
 
      ! -
 
 
 
      GSMATCH = LEQUAL.1.1
 
 
 
      ! +
 
      ! если имеются блоки данных, описанных с помощью опера-
 
      ! торов COMMON (в Фортране, Бейсике, Паскале), MAP (в
 
      ! Бейсике), GLOBALDEF (в ПЛ/1), PSECT_OBJECT (в языке
 
      ! АДА) либо аналогичных декларативных операторов дру-
 
      ! гих языков программирования, следует изменить атрибут
 
      ! SHR программных секций (PSECT), задаваемого средствами
 
      ! таких языков. Если не заменить атрибут SHR на NOSHR,
 
      ! будет сообщение об ошибке.
 
      !
 
      ! оператор PSECT_ATTR нужен для тех программных секций,
 
      ! у которых имеются одновременно атрибут WRT (возмо-
                                                 
      ! ность записи) и атрибут SHR (разделяемый).
 
      ! в данном примере предполагается, что в программе имеется
 
      ! общая область с именем GRA_COMMON. Замените GRA_COMMON
 
      ! именем соответствующей программной секции либо удалите
 
      ! этот оператор, если отсутствуют соответствующие
 
      ! программные секции.
 
      ! -
 
 
 
      PSECT_ATTR = GRA_COMMON,NOSHR
 
 


                                - 160 -
 
                           00152-01 97 08
 
 
      ! +
 
      ! убедитесь в том, что вектор передачи первым попа-
 
      ! дает в образ, что у всех программных секций, которые
 
      ! доступны только на считывание, имеются атрибуты PIC
 
      ! и EXE. Проанализируйте листинги с целью
 
      ! определения атрибутов различных программных секций.
 
      ! в данном примере программную секцию $PDATA, порож-
 
      ! денную Фортраном, следует сделать PIC и EXE.
 
      ! -
 
 
 
      PSECT_ATTR = $PDATA,PIC,EXE
 
 
 
      ! +
 
      ! следующими двумя строками команды и данные группиру-
 
      ! ются в кластеры секций образа для образа разделяемой
 
      ! библиотеки. Кластер секции образа - это группа вза-
 
      ! имосвязанных программных секций. Помещайте все дос-
 
      ! тупные только для считывания участки программ и
 
      ! данных (включая вектор передачи) в CLUSTER1.
 
      ! помещайте всю читаемую-записываемую информацию в
 
      ! CLUSTER2. Программные секции COMMON (или аналогичные)
 
      ! должны быть также помещены в CLUSTER2.
 
      !
 
      ! замените $$$$VECTOR именем той программной секции,
 
      ! которое было указано для вектора передачи, если
 
      ! оно отличается от данного. Приведенные здесь имена
 
      ! программных секций являются стандартными при порожде-
 
      ! нии секций языками программирования высокого уровня.
 
      ! по своему листингу проверьте наличие каких-либо
 
      ! других используемых имен программных секций.


                                - 161 -
 
                           00152-01 97 08
 
 
      ! -
 
 
 
      COLLECT = CLUSTER1,$$$$VECTOR,$CODE,$PDATA
 
      COLLECT = CLUSTER2,$LOCAL,$BLANK,GRA_COMMON
 
 
 
      ! +
 
      ! следующими строками перечисляются те модули,
 
      ! которые надлежит включить в библиотеку разделяемого
 
      ! образа. В данном примере предполагается, что все
 
      ! необходимые об'ектные модули находятся в библиотеке
 
      ! об'ектных модулей, которая называется GRA_OBJLIB.OLB.

      !
 
      ! следует явным образом указать имя об'ектного файла
 
      ! вектора передачи. Вектор передачи автоматически
 
      ! будет содержать ссылки на все определенные точки
 
      ! входа и все необходимые ссылки.
 
      !
 
      ! если требуется ссылаться на большее число модулей
 
      ! или библиотек, добавьте новые строки, содержащие
 
      ! имена соответствующих файлов.
 
      ! -
 
      !
 
      GRA_VECTOR.OBJ
 
      GRA_OBJLIB.OLB/LIBRARY
 
 
 
      ! +
 
      ! конец файла необязательных параметров компоновщика.
 
      ! -
 
 
 
 


                                - 162 -
 
                           00152-01 97 08
 
 
           5.2.4. Создание образа разделяемой библиотеки
 
 
           После того, как созданы вектор передачи и файл  необя-
 
      зательных параметров  компоновщикA,  все  подготовлено  для
 
      компоновки  образа  разделяемой  библиотеки.  Воспользуемся
 
      примером образа разделяемой библиотеки  для  средства  GRA,
 
      который назовем GRA_SHR. Тогда  команда  компоновки  образа
 
      будет иметь вид:
 
      $LINK/SHAREABLE=GRA_SHR.EXE/MAP=GRA_SHR.MAP/FULL-
 
                                    GRA_OPTIONS/OPTIONS
 
      компоновщик создаст образ разделяемой библиотеки  с  именем
 
      GRA_SHR.EXE, а также  создаст  файл  распределения  памяти,
 
      содержащий полезную информацию относительно скомпонованного
 
      образа в файле с именем GRA_SHR.MAP. Если также  желAтельно
 
      получить  таблицу  перекрестных   ссылок   идентификаторов,
 
      используемых в образе разделяемой библиотеки,  нужно  доба-
 
      вить  в  командную  строку  квалификатор  /CROSS_REFERENCE.
 
      (пользователю необходимо подставить  в  команду  компоновки
 
      вместо GRA_SHR и GRA_OPTIONS имя своего образа и имя  файла
 
      необязательных параметров компоновщика).
 
           Компоновщик должен завершить свою  работу  без  каких-
 
      либо сообщений об ошибках или иного  характера.  Существует
 
      одно сообщение-предупреждение,  которое  может  выдаваться,
 
      если какие-либо модули библиотеки написаны на  Макроассемб-
 
      лере либо языке Блисс системы МОС ВП  (данная  проблема  не
 
      возникает, если программы написаны на языках высокого уров-
 
      ня). Текст сообщения  таков:  "создающийся  образ  содержит
 
      ошибки в перемещаемых ссылках". И хотя операция  компоновки
 
      завершается успешно и можно будет пользоваться полученным в
 
      результате образом разделяемой  библиотеки,  будет  потерян
 


                                - 163 -
 
                           00152-01 97 08
 
 
      желаемый атрибут совместимости с будущими  изменениями  при
 
      компоновке нового образа или в  тех  случаях,  когда  будет
 
      перекомпонован образ, на который имеются  ссылки  в  образе
 
      разделяемой библиотеки. Причина данной ошибки заключается в
 
      ссылках на внешние идентификаторы без использования  общего
 
      режима (способа) адресации. При  программировании  на  мак-
 
      роассемблере необходимо поставить всем  внешним  ссылкам  в
 
      качестве префикса символы G^; при программировании на языке
 
      Блисс системы МОС ВП либо следует об'явить  внешнее  имя  с
 
      помощью атрибута ADDRESSING_MODE (общий случай), либо  вос-
 
      пользоваться оператором SWITCHES для принудительного  зада-
 
      ния  общего  режима  адресации  для  внешних  идентификато-
 
      ров
 
           После того, как образ скомпонован, необходимо по карте
 
      распределения памяти проверить, что  вектор  передачи  -  в
 
      данном примере программная секция $$$$VECTOR -  размещен  с
 
      базового адреса "нуль". Если этого  нет,  то,  по-видимому,
 
      потребуется изменить атрибуты некоторых программных  секций
 
      на PIC и EXE, как показано в шаблоне  файла  необязательных
 
      параметров компоновщика (п. 5.2.3) [7].
 
 
 
           5.2.5. Об'единение разделяемых  образов  в  библиотеку
 
      разделяемых образов
 
 
           При наличии нескольких разделяемых образов можно  соз-
 
      дать библиотеку разделяемых образов с помощью  команд  биб-
 
      лиотекаря. Формат команды, Kоторая используется для  созда-
 
      ния библиотеки разделяемых образов, таков:
 
      $LIBRARY/CREATE/SHARE имя_библиотеки разделяемый_образ1-
 
      [,разделяемый_образ2[,...]]
 


                                - 164 -
 
                           00152-01 97 08
 
 
           Параметр "имя_библиотеки" - это то имя, которое  поль-
 
      зователь присваивает библиотеке разделяемых образов.  Пара-
 
      метры "разделяемый_образ"  -  это  те  разделяемые  образы,
 
      которые желательно включить в библиотеку разделяемых  обра-
 
      зов.
 
 
 
           5.3. Компоновка с библиотеками модульных процедур
 
 
           Чтобы воспользоваться библиотекой модульных  процедур,
 
      будь то библиотека об'ектных модулей или библиотека  разде-
 
      ляемых образов, следует указать  имя  библиотеки  вместе  с
 
      квалификатором /LIBRARY в качестве одного из входных файлов
 
      команды LINK. Например:
 
      $ LINK MYPROG, OURLIB/LIBRARY
 
           В данном примере MYPROG.OBJ - это  основная  программа
 
      того, что будет выполняемым образом,  а  OURLIB.OLB  -  это
 
      либо библиотека об'ектных модулей, либо  библиотека  разде-
 
      ляемых образов. Если OURLIB - библиотека разделяемых  обра-
 
      зов и если образ разделяемой  библиотеки  не  резидентен  в
 
      системном каталоге SYS$LIBRARY:, следует  определить  логи-
 
      ческое имя для имени  разделяемого  образа,  чтобы  указать
 
      действительное местонахождение файла. Например:
 
      $ DEFINE GRA_SHR OURDISK:[OURLIB]GRA_SHR
 
      такое логическое имя  должно  быть  определено  до  запуска
 
      программы.
 


                                - 165 -
 
                           00152-01 97 08
 
 
                           6. Сопровождение
 
 
 
           6.1. Совместимость вперед
 
 
           Совместимость вперед является весьма важным положением
 
      этапа сопровождения. Если процедура совместима  вперед  (то
 
      есть не чувствительна к изменениям в будущем), то  внесение
 
      изменений и исправлений в процедуру не повлияет на выполне-
 
      ние и применение предшествующих версий такой процедуры.
 
           Представим себе,  например,  написанную  пользователем
 
      процедуру с именем LIB_TOTAL_BILL. Пусть вызывающая  после-
 
      довательность для такой процедуры будет следующей:
 
      CALL LIB_TOTAL_BILL (цена, налог)
 
           Предположим, что пользователь, который  написал  такую
 
      процедуру, решил видоизменить процедуру  с  тем,  чтобы  ее
 
      можно было использовать для вычисления итоговых  счетов  по
 
      кредитным картам пользователей-покупателей. Для этого  пот-
 
      ребуется добавить третий параметр  -  "интерес".  Для  того
 
      чтобы обеспечить совместимость вперед, добавление параметра
 
      "интерес" не должно противоречить тому, как раньше работала
 
      процедура. Новая вызывающая последовательность будет выгля-
 
      деть следующим образом:
 
      CALL LIB_TOTAL_BILL (цена, налог [, интерес])
 
           Процедура должна быть написана  таким  образом,  чтобы
 
      пользователь мог обращаться к процедуре так же, как и рань-
 
      ше, просто опуская параметр "интерес".
 
           Если в измененной версии такой процедуры  пользователь
 
      может все же придерживаться  вызывающей  последовательности
 
      предшествующей версии, говорят, что процедура обладает сов-
 
      местимостью вперед.
 


                                - 166 -
 
                           00152-01 97 08
 
 
           6.1.1. Основные правила
 
 
           Чтобы обеспечить совместимость со всеми будущими  вер-
 
      сиями разделяемого образа,  процедуры  разделяемого  образа
 
      должны соответствовать следующим правилам (в  дополнение  к
 
      правилам модульного программирования в системе МОС ВП):
 
           - ссылка на точку входа процедуры осуществляется через
 
      вектор передачи (п. 5.2.2);
 
           - код и данные процедуры должны быть позиционно  неза-
 
      висимыми.
 
 
 
           6.1.2. Регрессионное тестирование
 
 
           Регрессионное тестирование представляет способ провер-
 
      ки того, что добавление новых возможностей в  процедуру  не
 
      влияет на правильное выполнение ранее оттестированных  воз-
 
      можностей. При регрессионной проверке прогоняются  установ-
 
      ленные  тесты  программного  обеспечения   и   сравниваются
 
      результаты тестов с тем, что предполагалось получить.  Если
 
      реальные результаты не совпадают с тем,  что  ожидалось,  в
 
      тестируемом программном обеспечении возможны  ошибки.  Если
 
      ошибки действительно  есть,  то  говорят,  что  тестируемое
 
      программное обеспечение "ухудшилось".
 
           При регрессионной проверке осуществляется пять шагов:
 
           1) создание тестов.  Следует  создать  тесты,  написав
 
      командные файлы для тестирования программного обеспечения;
 
           2) организация тестов. Следует организовать файлы тес-
 
      тов так, чтобы достаточно просто получать к ним  доступ  по
 
      мере необходимости;
 
           3) прогон тестов. Для того  чтобы  прогнать  одиночный
 
      тест, нужно подключить его командный файл к очереди  пакет-


                                - 167 -
 
                           00152-01 97 08
 
 
      ной обработки. Для того чтобы  прогнать  несколько  тестов,
 
      нужно создать командный файл, который будет подключать каж-
 
      дый тест к очереди пакетной обработки;
 
           4) вычисление  результатов  тестирования.  Вычисление
 
      ожидаемых  результатов  тестирования  осуществляется   либо
 
      вручную, либо с  помощью  ранее  проверенного  программного
 
      обеспечения;
 
           5) сравнение результатов. Сравниваются  действительные
 
      (полученные) результаты тестирования с ожидавшимися резуль-
 
      татами. Если имеются несоответствия, повторяются вычисления
 
      на шаге 4. Если несоответствие все же сохраняется,  следует
 
      проанализировать те изменения, которые были сделаны в прог-
 
      раммном обеспечении, в целях обнаружения ошибки.
 
           Важно, чтобы были написаны новые тесты и чтобы  повто-
 
      рялись шаги регрессионной проверки всякий раз, когда проце-
 
      дуре добавляются новые функциональные возможности. Если  не
 
      проводить  регрессионных  проверок  при  каждом  расширении
 
      функциональных возможностей, процедура  может  стать  менее
 
      работоспособной, а ошибки останутся необнаруженными.
 
 
 
           6.1.2.1. Коррекция вектора передачи
 
 
           Чтобы изменить вектор  передачи,  требуется  выполнить
 
      три действия:
 
           1) добавление новой точки входа или новых точек входа.
 
      Для поддержания совместимости вперед при внесении изменений
 
      в библиотеку процедур важно не нарушать порядок  существую-
 
      щих элементов вектора передачи.  Следует  всегда  добавлять
 
      новые элементы в конец вектора передачи и не  следует  уда-
 
      лять либо перестанавливать существующие. Если придерживать-
 


                                - 168 -
 
                           00152-01 97 08
 
 
      ся этих положений, при внесении изменений в вектор передачи
 
      не будет возникать никаких  проблем,  а  разделяемый  образ
 
      будет совместимым вперед;
 
           2) если предполагается наличие  проблемы  с  совмести-
 
      мостью, следует проверить вектор передачи. Проверить вектор
 
      передачи можно, сравнив адреса  точек  входа,  имеющиеся  в
 
      файле  листинга,  сгенерированном  при  трансляции  вектора
 
      передачи, с адресами точек  входа  по  листингу  предыдущей
 
      версии вектора передачи. Поэтому всегда  следует  сохранять
 
      копию предыдущих файлов  листингов.  При  сравнении  файлов
 
      нужно убедиться, что не изменились адреса  идентификаторов.
 
      Если все идентификаторы предшествующей версии содержатся  в
 
      текущей версии и относительные адреса таких идентификаторов
 
      не изменились, то вектор передачи был изменен с учетом сов-
 
      местимости вперед, а существующие  программы,  использующие
 
      идентификаторы из вектора передачи, будут оставаться верны-
 
      ми;
 
           3)  скорректировать  младшую  (второстепенную)   часть
 
      идентификатора глобальной  секции  в  файле  необязательных
 
      параметров компоновщика (см. п. 5.2.3).
 
 
 
           6.2. Добавление параметров в существующую подпрограмму
 
 
           В ходе нормального цикла сопровождения  иногда  возни-
 
      кает необходимость передать новую или дополнительную инфор-
 
      мацию существующей процедуре, а не создавать новую процеду-
 
      ру. Такую информацию можно передать процедуре одним из сле-
 
      дующих двух способов:
 
           1) непосредственно, добавив новые параметры в процеду-
 
      ру;
 


                                - 169 -
 
                           00152-01 97 08
 
 
           2) используя блок параметров.
 
 
 
           6.2.1. Добавление новых параметров в процедуру
 
 
           При непосредственном  добавлении  новых  параметров  в
 
      процедуру необходимо соблюдать два правила:
 
           1) новые параметры следует добавлять в  конец  сущест-
 
      вующего списка параметров;
 
           2) новые параметры должны быть необязательными.
 
           Для сохранения совместимости вперед важно, чтобы новые
 
      параметры были добавлены в конец существующего списка пара-
 
      метров.  Если  изменить  порядок  существующих  параметров,
 
      поместив новые параметры в начало или середину списка,  все
 
      прикладные программы, написанные с использованием  предыду-
 
      щей версии процедуры, будут неработоспособными.
 
           Процедура  пользователя  также  должна   рассматривать
 
      новый параметр как необязательный. Если новый параметр ста-
 
      нет обязательным, то программы,  в  которых  использовалась
 
      предыдущая версия процедуры, будут неработоспособными.
 
           Поскольку трудно себе представить, что все  написанные
 
      ранее прикладные программы будут переписаны для того, чтобы
 
      содержать новый параметр процедуры, процедура должна прове-
 
      рять наличие параметра прежде, чем пытаться  осуществить  к
 
      нему доступ. Если процедура  не  проверяет  наличие  нового
 
      параметра и пытается осуществить доступ к параметру,  когда
 
      он отсутствует, результаты будут непредсказуемыми.
 
           Механизм передачи нового параметра должен соответство-
 
      вать основным положениям (п. 2.2.1).
 


                                - 170 -
 
                           00152-01 97 08
 
 
           6.2.2. Использование блока параметров
 
 
           При использовании блока параметров отпадает  необходи-
 
      мость добавлять параметры в  процедуру.  При  использовании
 
      блока параметров вызывающая  программа  передает  вызванной
 
      процедуре всего один параметр. Этот  параметр  представляет
 
      собой адрес блока параметров. Блок параметров -  это  блок,
 
      содержащий любую информацию, относительно  которой  сущест-
 
      вует соглашение между вызывающей и вызываемой  процедурами.
 
      Такая информация необходима вызываемой процедуре для  того,
 
      чтобы выполнить свою задачу.
 
           Сам блок  параметров  представляет  собой  непрерывный
 
      участок виртуальной памяти. Содержащаяся в  нем  информация
 
      может представлять числовую или скалярную информацию, деск-
 
      рипторы, векторы битов и  т.д.  формат  блока  определяется
 
      соглашением между пользователями процедуры и ее разработчи-
 
      ком.
 
           В первом длинном  слове  блока  параметров  содержится
 
      длина блока. Длина может выражаться в байтах, длинных  сло-
 
      вах либо в чем-то еще, но она должна быть согласована обеи-
 
      ми сторонами, реализована и задокументирована.
 
           Одним из примеров блока параметров может служить  век-
 
      тор параметра сигнала, используемый при обработке  исключи-
 
      тельной ситуации. Обращение к программе обработки  исключи-
 
      тельных состояний происходит с вектором параметра сигнала и
 
      вектором параметра механизма. Каждый вектор является приме-
 
      ром блока параметров. Вектор параметра сигнала, приведенный
 
      на рис. 12, является примером блока параметров.
 


                                - 171 -
 
                           00152-01 97 08
 
 
            Блок параметров - вектор параметра сигнала
 
 
      -----------------------------------------------------
      !                                                   !
      !Количество длинных слов информации, следующей  за  !
      !                                                   !
      !данным словом                                      !
      !                                                   !
      -----------------------------------------------------
      !                                                   !
      !Значение условия                                   !
      !                                                   !
      -----------------------------------------------------
                    .
                    .
                    .  Необязательные параметры,
 
                    .  Дающие дополнительную
 
                    .  Информацию относительно
 
                    .  Исключительного состояния
                    .
                    .
      ------------------------------------------------------
      !                                                    !
      !Счетчик адреса программы (PC) в момент возникновения!
      !                                                    !
      !исключительного состояния (прерывания)              !
      !                                                    !
      ------------------------------------------------------
      !                                                    !
      !Длинное слово состояния программы (PSL) в момент    !
      !                                                    !
      !возникновения исключительного состояния             !
      !                                                    !
      ------------------------------------------------------
 
                               Рис. 12
 
           В первом длинном слове вектор параметра сигнала содер-
 
      жит количество длинных слов реальной информации. То,  какая
 
      информация в действительности следует, зависит от  значения
 
      исключительного состояния сигнала.
 
           Если удлиняется блок параметров в целях передачи новой
 
      информации вызываемой процедуре, последняя должна проверить
 
      длину блока  параметров  на  допустимость  перед  тем,  как
 
      пытаться осуществить доступ к информации. Как и для  случая
 
      добавления новых параметров при  непосредственной  передаче
 


                                - 172 -
 
                           00152-01 97 08
 
 
      параметров процедуре, вызывающая программа могла быть напи-
 
      сана так, что передает более короткий блок параметров. Если
 
      процедура не проверяет длину блока и  пытается  осуществить
 
      доступ к информации, расположенной за  концом  фактического
 
      блока параметров, результаты будут непредсказуемыми.
 
 
 
           6.3. Корректировка библиотек
 
 
           Всякий раз, когда производятся изменения  или  усовер-
 
      шенствования модульных процедур,  которые  являются  частью
 
      некоторой библиотеки, должна быть  изменена  и  библиотека,
 
      содержащая процедуру (процедуры), чтобы библиотека отражала
 
      новые или измененные процедуры.
 
 
 
           6.3.1. Корректировка об'ектных библиотек
 
 
           Если  измененная  процедура  (процедуры)  находится  в
 
      об'ектной библиотеке,  потребуется  изменить  библиотеку  с
 
      тем, чтобы при последующих доступах к библиотеке с  помощью
 
      команды LINK или других команд доступ происходил к  об'ект-
 
      ным модулям, соответствующим новым или измененным  процеду-
 
      рам.
 
           Для того чтобы изменить об'ектную библиотеку,  следует
 
      воспользоваться командой LIBRARY с квалификаторами  REPLACE
 
      и OBJECT в следующем виде:
 
      $ LIBRARY/REPLACE/OBJECT имя_библиотеки-
 
      спецификация_файла[,...]
 
      в данном примере "имя_библиотеки" - это имя, которое  прис-
 
      воено библиотеке.  По  умолчанию  для  имени  библиотеки  в
 
      качестве типа файла принимается OLB. Имя  об'ектного  моду-
 
      ля - это "спецификации_файла". По умолчанию для  об'ектного


                                - 173 -
 
                           00152-01 97 08
 
 
      модуля тип файла OBJ.
 
 
 
           6.3.2. Корректировка разделяемых образов
 
 
           Если измененная процедура (процедуры) является  частью
 
      разделяемого образа,  следует  перекомпоновать  разделяемый
 
      образ с тем, чтобы он содержал новые или измененные  версии
 
      всех измененных об'ектных модулей. Если  добавляются  новые
 
      процедуры, следует изменить вектор передачи и  перетрансли-
 
      ровать его до операции перекомпоновки разделяемого  образа.
 
      Если изменен вектор передачи, младшее идентифицирующее зна-
 
      чение GSMATCH должно быть увеличено на единицу.  Когда  это
 
      будет сделано, можно перекомпоновать разделяемый образ.
 
 
 
           6.3.2.1. Изменение вектора передачи
 
 
           Важно, чтобы изменения вектора передачи происходили  с
 
      учетом совместимости вперед для сохранения работоспособнос-
 
      ти существующих программ, которые используют содержащиеся в
 
      нем идентификаторы.
 
           В целях предотвращения несоответствия вектора передачи
 
      необходимо придерживаться следующих правил:
 
           - не изменять порядок существующих  идентификаторов  в
 
      векторе передачи;
 
           - не удалять никаких существующих  идентификаторов  из
 
      вектора передачи;
 
           - добавлять новые идентификаторы в конец существующего
 
      вектора передачи.
 
           После завершения внесения изменений в вектор  передачи
 
      его надо оттранслировать и проанализировать имена и относи-
 
      тельные адреса, присвоенные идентификаторам в модуле с тем,


                                - 174 -
 
                           00152-01 97 08
 
 
      чтобы гарантировать наличие всех ранее существовавших иден-
 
      тификаторов и то, что относительные адреса таких  идентифи-
 
      каторов не  изменились.  Если  существующие  идентификаторы
 
      были удалены или  перемещены,  то  существующие  программы,
 
      использующие разделяемый образ, станут неработоспособными.
 
 
 
           6.3.2.2. Корректировка файла необязательных параметров
 
      компоновщика
 
 
           При каждом изменении вектора передачи необходимо изме-
 
      нить ряд параметров в файле необязательных параметров  ком-
 
      поновщика:
 
           - увеличить часть, относящуюся к младшему  идентифици-
 
      рующему значению цепочки идентификации совпадения  глобаль-
 
      ной секции. Изменение младшего  идентифицирующего  значения
 
      будет обеспечивать компоновку программ с новой версией раз-
 
      деляемого образа без активизации старой версии  (в  которой
 
      может не содержаться новых процедур).  Значения  параметров
 
      идентификации совпадения (соответствия)  глобальной  секции
 
      устанавливаются   с   помощью   необязательного   параметра
 
      GSMATCH;
 
           - при  необходимости  добавить  информацию   о   новых
 
      об'ектных модулях, которые следует включить  в  разделяемый
 
      образ, в файл необязательных параметров компоновщика;
 
           - изменить в  строке  идентификации  номер  версии  на
 
      новое значение.
 


                                - 175 -
 
                           00152-01 97 08
 
 
           6.3.3. Корректировка библиотек разделяемых образов
 
 
           Если измененная процедура (процедуры) находится в раз-
 
      деляемом образе, который является частью библиотеки  разде-
 
      ляемых образов, требуется изменить  библиотеку  разделяемых
 
      образов с тем, чтобы все последующие доступы к  такой  биб-
 
      лиотеке посредством команды LINK осуществлялись к  изменен-
 
      ной версии разделяемого образа.
 
           Для изменения библиотеки разделяемых  образов  следует
 
      воспользоваться командой LIBRARY с квалификаторами  REPLACE
 
      и SHARE. Команда имеет вид:
 
      $LIBRARY /REPLACE/SHARE имя_библиотеки спецификация-
 
      _файла[,...]
 
      в дAнном примере "имя_библиотеки" -  это  то  имя,  которое
 
      присвоено библиотеке. По умолчанию тип файла имени  библио-
 
      теки OLB. Имя образа - это "спецификация_ файла". При  этом
 
      по умолчанию тип файла EXE.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 176 -
 
                           00152-01 97 08
 
 
                                                     Приложение 1
 
 
 
 
                  Правила модульного программирования
 
 
 
           Настоящее приложение представляет правила по написанию
 
      модульных процедур на любом из языков программирования сис-
 
      темы МОС ВП. Данные правила  -  это  тот  минимум,  который
 
      необходим для сопряжения  программного  обеспечения  уровня
 
      вызываемых процедур пользователя  с  программным  обеспече-
 
      нием, написанными другими пользователями, и наоборот.
 
           Несоблюдение каких-либо правил должно быть отражено  в
 
      документации на процедуру пользователя.
 
           В последующих разделах каждый элемент правил освещает-
 
      ся более подробно. Если для обеспечения модульности не тре-
 
      буется соблюдать  положения  данного  правила,  указывается
 
      слово "необязательный".
 
 
 
 
                            1. Назначение
 
 
 
           Большая часть настоящих правил получена  в  результате
 
      ответа на вопрос: "какие соглашения общего характера  необ-
 
      ходимо соблюдать между программистами для того, чтобы напи-
 
      санные ими процедуры могли работать так, как ожидается, при
 
      том,  что  они  об'единяются   в   программу   произвольным
 
      образом?".
 
           Это означает, что процедура, не  соответствующая  нас-
 
      тоящим правилам, может привести к тому, что другая  модуль-
 
      ная процедура, присутствующая  в  образе  программы,  будет
 
      работать неверно.


                                - 177 -
 
                           00152-01 97 08
 
 
           К произвольным способам об'единения процедур  относят-
 
      ся:
 
           - данная процедура вызывает другие процедуры;
 
           - другие процедуры вызывают данную процедуру;
 
           - вызывающая программа вызывает либо данную процедуру,
 
      либо другие процедуры.
 
           Правила модульного программирования в системе  МОС  ВП
 
      были разработаны с целью создать  для  программистов  общую
 
      среду, в которой они будут кодировать свои программы.  Если
 
      все программисты будут придерживаться настоящих правил,  то
 
      любую модульную процедуру можно будет добавить в библиотеку
 
      процедур без того, чтобы возникали конфликтные  ситуации  с
 
      любыми уже находящимися в  библиотеке  процедурами  либо  с
 
      процедурами, которые, возможно, добавятся в будущем.
 
 
 
 
                        2. Область применения
 
 
 
           Настоящие правила относятся к библиотечным  процедурам
 
      и рекомендованы для прочих видов программного  обеспечения,
 
      включая обслуживающие и прикладные программы.  Все  постав-
 
      ляемые и реализованные в системе МОС ВП языки  программиро-
 
      вания позволяют писать процедуры, соответствующие настоящим
 
      правилам. Настоящие правила относятся к тем  процедурам,  у
 
      которых имеется общедоступная  точка  входа.  Общедоступная
 
      точка входа - это такая точка входа, местоположение которой
 
      сможет найти компоновщик посредством поиска в  используемых
 
      по умолчанию системных библиотеках. Данные правила не  при-
 
      менимы к вызовам подпрограмм,  внутренних  по  отношению  к
 
      модулю, у которых отсутствуют  общедоступные  точки  входа,
 


                                - 178 -
 
                           00152-01 97 08
 
 
      хотя набор процедур в целом и соответствует  данным  прави-
 
      лам.
 
 
 
 
                        3. Правила кодирования
 
 
 
           Следующие правила относятся ко  всем  процедурам.  Эти
 
      правила сгруппированы по категориям:
 
           - интерфейс при вызове;
 
           - инициализация;
 
           - сообщение об исключительных условиях;
 
           - реентерабEльность по AST;
 
           - распределение ресурса;
 
           - формат и содержание закодированных модулей;
 
           - разделяемые образы;
 
           - совместимость вперед.
 
 
 
           3.1. Интерфейс при вызове
 
 
           Правила для интерфейса при вызове:
 
           1) вызовы процедур должны соответствовать  принятым  в
 
      системе МОС ВП правилам вызова процедур и  обработки  усло-
 
      вий. Некоторыми элементами правил очерчивается подмножество
 
      процедур для увеличения возможности процедур вызывать  друг
 
      друга [5];
 
           2) в процедуре не  должно  быть  каких-либо  допущений
 
      относительно ее рабочей среды, отличные от оговоренных нас-
 
      тоящими правилами. В частности, для  того  чтобы  работать,
 
      как указано, процедура не должна делать  никаких  допущений
 
      относительно вызывающей программы  и  не  выдвигать  к  ней
 
      каких-либо требований;


                                - 179 -
 
                           00152-01 97 08
 
 
           3) процедура не должна вызывать другие  процедуры  или
 
      средства  системного  обслуживания,  если  получающаяся   в
 
      результате комбинация программных средств нарушает  настоя-
 
      щие правила с точки зрения вызывающей программы.  Процедура
 
      может вызывать другие  процедуры  или  средства  системного
 
      обслуживания, которые не соблюдают  необязательные  правила
 
      настоящего приложения. Вместе с тем,  если  получающаяся  в
 
      результате комбинация (как видно из  вызывающей  программы)
 
      не соответствует необязательным элементам,  в  документации
 
      вызывающей процедуры должно  быть  отражено  такое  несоот-
 
      ветствие;
 
           4) модульная процедура должна обеспечивать интерфейс с
 
      вызывающими ее программами таким образом, чтобы  вызывающие
 
      программы могли следовать всем обязательным элементам  нас-
 
      тоящих правил;
 
           5) у каждого модуля должна быть только  одна  общедос-
 
      тупная точка входа (необязательный элемент);
 
           6) если в процедуре используется точка JSB, она  также
 
      должна обеспечить эквивалентную точку входа вызова для сох-
 
      ранения независимости от языка программирования. Это требо-
 
      вание продиктовано тем, что хотя вызывающие  последователь-
 
      ности JSB могут выполняться быстрее, чем  вызовы  процедур,
 
      явная компоновка вызова типа JSB к  внешней  программе  или
 
      подпрограмме может не обеспечиваться имеющимися  средствами
 
      некоторых языков программирования высокого уровня.  (необя-
 
      зательный элемент);
 
           7) порядок требующихся параметров  должен  быть  таким
 
      же, как порядок аппаратных команд системы MOC ВП,  то  есть
 
      чтение, модификация, запись. Необязательные параметры долж-
 
      ны располагаться в том же порядке. Вместе с  тем  (согласно


                                - 180 -
 
                           00152-01 97 08
 
 
      правилам вызова процедур и обработки  исключительных  усло-
 
      вий), если значение функции нельзя представить на 64 разря-
 
      дах или оно типа строки символов, первым параметром  указы-
 
      вается, где запомнить значение  функции,  а  все  остальные
 
      параметры сдвигаются на одно место вправо;
 
           8) вызывающая  процедуру  программа  должна  указывать
 
      опущенные необязательные параметры, помещая в  передаваемый
 
      список параметров в соответствующие точки нули (для  непос-
 
      ледних в списке  параметров),  либо  передавая  укороченный
 
      список параметров (если  опускаются  последние  параметры).
 
      Однако средства системного обслуживания нуждаются в опущен-
 
      ных параметрах (должны быть заполнены нулями)  и  не  соот-
 
      ветствуют данному положению (необязательный элемент);
 
           9) строковые параметры (цепочки символов) должны всег-
 
      да передаваться посредством дескриптора;
 
           10) процедуры не должны получать или возвращать инфор-
 
      мацию вызывающим их программам с помощью  неявных  перекры-
 
      ваемых программных секций либо через неявные поля  глобаль-
 
      ных данных. Все получаемые от вызывающей программы и  возв-
 
      ращаемые ей параметры должны использовать список параметров
 
      и регистры значения функции (R0 и R0/R1);
 
           11) в процедуре нельзя рассчитывать на то, что неявные
 
      выходные данные процедур, к которым она  обращается,  оста-
 
      нутся неизменными, если впоследствии  они  будут  использо-
 
      ваться в качестве входных данных теми же процедурами и свя-
 
      занными с ними процедурами;
 
           12) все программы пользователя должны быть  позиционно
 
      независимыми. Данные необязательно должны  быть  позиционно
 
      независимыми. Вместе с тем, для улучшения производительнос-
 
      ти данные следует изначально обнулить на  этапе  компиляции


                                - 181 -
 
                           00152-01 97 08
 
 
      или компоновки в целях предотвращения возможности возникно-
 
      вения позиционно зависимых констант либо позиционно зависи-
 
      мых адресов;
 
           13) в позиционно независимых ссыках (в некотором моду-
 
      ле) на  другую  программную  секцию  должна  использоваться
 
      относительная адресация (длиной в два слова) с  тем,  чтобы
 
      компоновщик смог правильно разместить в произвольном  месте
 
      программные  секции  данных  с  учетом  программных  секций
 
      команд вне зависимости от того,  какое  количество  модулей
 
      содержит программа;
 
           14) при внешних ссылках необходимо использовать  адре-
 
      сацию общего режима с тем, чтобы любая процедура, на  кото-
 
      рую имеется ссылка, могла быть помещена в разделяемый образ
 
      без необходимости внесения изменений в вызывающую  програм-
 
      му;
 
           15) процедуры не  могут  требовать  от  вызывающих  их
 
      программ передавать им дескрипторы динамических строк;
 
           16) некоторые спецификации интерфейса процедуры сохра-
 
      няют статическую информацию от  одного  вызова  до  другого
 
      даже в тех случаях, когда процедуры не связаны с  распреде-
 
      лением ресурса. В описании интерфейса используется одна  из
 
      следующих методик для того, чтобы можно  было  осуществлять
 
      последовательности вызовов из независимых частей программы.
 
      Такими методиками либо исключается использование  статичес-
 
      кой памяти, либо устраняются связанные с ее  использованием
 
      ограничения (приведены в порядке убывания их предпочтитель-
 
      ности):
 
 
           - спецификация интерфейса состоит из последовательнос-
 
      ти вызывов к набору из одной или нескольких процедур - пер-
 


                                - 182 -
 
                           00152-01 97 08
 
 
      вая процедура распределяет память и возвращает (в  качестве
 
      выходного параметра вызывающей программе) или адрес  массо-
 
      вой памяти  или  некоторое  другое  значение-идентификатор,
 
      имеющее смысл в рамках процесса в  целом.  Данный  параметр
 
      передается другим процедурам вызывающей программой явно,  а
 
      последняя процедура освобождает массовую память или иденти-
 
      фицирующее значение, имеющее  смысл  в  рамках  процесса  в
 
      целом;
 
           - программа, вызывающая процедуру, производит  распре-
 
      деление всей памяти и передает адрес при каждом вызове;
 
           - спецификация интерфейса состоит из одного вызова,  в
 
      котором вызывающая программа передает адрес одной или  нес-
 
      кольких пользовательских программ развязки и  тех  парамет-
 
      ров, которые должны быть им  переданы.  Процедура  вызывает
 
      пользовательскую программу развязки в процессе своей  рабо-
 
      ты. Результаты сохраняются процедурой на время вызова поль-
 
      зовательской  программы  (программ)  развязки  (статическая
 
      память не используется);
 
           - спецификация интерфейса содержит  последовательность
 
      вызывов к набору из одной или нескольких  процедур.  Первая
 
      процедура, наряду с прочими вещами,  запоминает  содержимое
 
      всей все еще активной статической памяти в стеке,  располо-
 
      женном в массовой памяти,  а  последняя  процедура,  помимо
 
      всего прочего, восстанавливает старое содержимое  статичес-
 
      кой памяти. Таким образом,  статическая  память  становится
 
      доступной для передачи неявных параметров от одной процеду-
 
      ры к следующей в  последовательности  вызовов  (неизвестной
 
      вызывающей программе). Однако, если где-то в последователь-
 
      ности возникает исключительное состояние, вызывающая  прог-
 
      рамма должна  указать  программу  обработки  исключительных


                                - 183 -
 
                           00152-01 97 08
 
 
      состояний, которой вызывается последняя процедура в  случае
 
      раскрутки стека  (для  восстановления  старого  содержимого
 
      статической памяти).
 
 
 
           3.2. Инициализация
 
 
           Если процедура требует инициализации один раз для каж-
 
      дой активизации  образа,  такая  операция  выполняется  без
 
      извещения вызвавшей программы одним из следующих способов:
 
           1) инициализацией на этапе компилирования;
 
           2) инициализацией на этапе компоновки;
 
           3) добавлением адреса  диспетчеризации  в  программную
 
      секцию LIB$INITIALIZE;
 
           4) проверкой и установкой статически выделенного флага
 
      первого входа при каждом вызове.
 
           Процедура не должна  использовать  LIB$INITIALIZE  для
 
      указания программы обработки исключительных состояний перед
 
      вызовом основной программы, если ее работа может противоре-
 
      чить работе прочих программ обработки  исключительных  сос-
 
      тояний, об'явленных перед основной программой.
 
 
 
           3.3. Сообщение об исключительных условиях
 
 
           Процедура не  должна  выводить  никаких  сообщений  об
 
      ошибках или сообщений информационного  порядка  либо  явно,
 
      либо посредством вызова программы  системного  обслуживания
 
      $PUTMSG. Процедура должна либо возвращать значение исключи-
 
      тельного состояния в регистре R0 в качестве значения  функ-
 
      ции, либо вызвать LIB$SIGNAL или LIB$STOP для  вывода  всех
 
      сообщений (процедуры LIB$SIGNAL и LIB$STOP могут вызываться
 
      либо явно, либо косвенно).


                                - 184 -
 
                           00152-01 97 08
 
 
           3.4. Реентерабельность  с   точки   зрения   обработки
 
      асинхронных системных прерываний
 
 
           Чтобы быть реентерабельной по  AST,  процедура  должна
 
      работать правильно и тогда, когда  между  любыми  ее  двумя
 
      инструкциями может быть вызвана любая процедура (включая ее
 
      саму). TAкая процедура может быть процедурой уровня  асинх-
 
      ронных системных прерываний, программой обработки  исключи-
 
      тельного состояния или другой  процедурой,  реентерабельной
 
      по AST.
 
           Процедура, которая не использует статической памяти  и
 
      вызывает только процедуры, реентерабельные по AST,  автома-
 
      тически является реентерабельной с точки  зрения  обработки
 
      асинхронных системных прерываний.
 
           Если  процедура  использует  статическую  память,  она
 
      должна использовать один из следующих  способов  для  того,
 
      чтобы ее можно было вызывать как с уровня асинхронных  сис-
 
      темных прерываний, так и с другого уровня:
 
           1) выполнять доступ и изменения в базе данных в  одной
 
      непрерываемой команде. Сделать это можно только из програм-
 
      мы на языке Макро системы МОС ВП;  эмулируемые  команды  не
 
      допускаются;
 
           2) определять наличие  параллельного  доступа  к  базе
 
      данных с помощью команд "проверить и установить" при каждом
 
      доступе к базе данных;
 
           3) сохранять счетчик числа текущих вызывов увеличенным
 
      на единицу при входе в процедуру и уменьшенным  на  единицу
 
      при выходе;
 
           4) блокировать асинхронные  системные  прерывания  при
 
      входе в процедуру и восстанавливать разрешение  асинхронных
 


                                - 185 -
 
                           00152-01 97 08
 
 
      системных прерываний (их текущее состояние) при выходе.
 
           Если процедура выполняет ввод-вывод с уровня асинхрон-
 
      ных системных прерываний посредством обращения к  средствам
 
      системного обслуживания $GET и $PUT СУД-32, процедура долж-
 
      на проверять состояние ошибки действующего  потока  записей
 
      (RMS$_RSA). Если данная ошибка обнаружится, процедура обра-
 
      щается к программе системного обслуживания $WAIT,  а  затем
 
      повторяет запросы к средствам системного обслуживания  $GET
 
      или $FUT.
 
           Процедура не должна зависеть от того, заблокированы ли
 
      асинхронные системные  прерывания  для  правильной  работы,
 
      если возможно использовать другие приемы  программирования.
 
      Например, программы завершения операции СУД-32  реализуются
 
      посредством асинхронных  системных  прерываний,  и  они  не
 
      будут работать, если  заблокировать  асинхронные  системные
 
      прерывания.
 
 
 
           3.5. Распределение ресурсов
 
 
           Процедура не должна занимать для своих нужд  статичес-
 
      кую память, если только не одно из двух:
 
           1) это - процедура  распределяемого  ресурса,  имеющая
 
      смысл в рамках процесса в целом;
 
           2) процедура должна сохранять  результат  для  неявных
 
      входных данных при последующих обращениях.
 
           Процедуры обслуживания запросов  времени  и  процедуры
 
      распределения ресурсов должны обеспечить значения статисти-
 
      ческих характеристик для оценки производительности и отлад-
 
      ки, обеспечивая точки входа типа средство_SHOW_имя и
 


                                - 186 -
 
                           00152-01 97 08
 
 
      средство_STAT_имя  (необязательный элемент).
 
           Если процедурой  используется  общий  для  процесса  в
 
      целом ресурс, она обращается за выделением ресурса к  соот-
 
      ветствующей процедуре распределения ресурса  или  программе
 
      системного обслуживания с тем, чтобы  избежать  конфликтных
 
      ситуаций по распределению  ресурсов,  которые  производятся
 
      другими. Для того чтобы сохранить ресурс,  процедура,  тре-
 
      бующая распределения ресурса, выполняет одно из следующих:
 
           1) перед  передачей  управления  вызывающей  программе
 
      вызывает процедуру освобождения ресурса;
 
           2) запоминает место в статической памяти и позже обра-
 
      щается к процедуре освобождения ресурса;
 
           3) передает ответственность  за  освобождение  ресурса
 
      вызывающей программе;
 
           4)  выделяет  фиксированное  количество  ресурсов  вне
 
      зависимости от того, сколько раз она вызывается.
 
 
 
           3.6. Формат и содержание закодированных модулей
 
 
           Каждый   модуль   должен   содержать  описание  модуля
 
           Каждая процедура должна содержать описание процедуры.
 
           Если требуется согласовать определения идентификаторов
 
      в нескольких модулях (например, блоки управления,  значения
 
      параметров процедуры и коды признаков завершения),  опреде-
 
      ления (описания) должны быть сосредоточены в общем исходном
 
      файле. Модули должны быть написаны на одном языке  програм-
 
      мирования.
 
           Команды и  операторы  должны  записываться  заглавными
 
      буквами, тогда как комментарии  -  заглавными  и  строчными
 
      символами (необязательный элемент).
 


                                - 187 -
 
                           00152-01 97 08
 
 
           Для улучшения читаемости  следует  добавлять  необяза-
 
      тельные пробелы (необязательный элемент).
 
           Следует пользоваться  блоками  комментариев  (необяза-
 
      тельный элемент).
 
           Следует пользоваться идентификаторами, а не числами  в
 
      теле процедуры (необязательный элемент).
 
           Имена точек входа процедуры,  имена  модулей  и  имена
 
      программных секций должны  соответствовать  соглашениям  по
 
      наименованию об'ектов.
 
           Рекомендуется также придерживаться соглашений по  наи-
 
      менованию при выборе имен для средств  и  файлов  (необяза-
 
      тельный элемент).
 
 
 
           3.7. Разделяемые образы
 
 
           Код процедуры  является  позиционно  независимым.  Для
 
      всех ссылок на внешние ячейки,  например,  на  точки  входа
 
      программ системного обслуживания системы  МОС  ВП,  следует
 
      использовать режим  общей  адресации  (необязательный  эле-
 
      мент).
 
 
 
           3.8. Совместимость вперед
 
 
           Если новая версия процедуры замещает существующую биб-
 
      лиотечную процедуру, все новые параметры следует  добавлять
 
      в конец вызывающей последовательности и их сделать необяза-
 
      тельными для сохранения совместимости вперед  (необязатель-
 
      ный элемент).
 
           Точки  входа  процедуры  делают  векторOM  с   помощью
 
      отдельного модуля на Макроассемблере, содержащего описатель
 
      TRANSFER (необязательный элемент).


                                - 188 -
 
                           00152-01 97 08
 
 
           Команды и данные процедуры являются позиционно незави-
 
      симыми.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 189 -
 
                           00152-01 97 08
 
 
                                                     Приложение 2
 
 
 
 
                       Характеристики параметров
 
 
 
           Каждый явный параметр описывается в терминах системно-
 
      го применения, типов данных, механизмов доступа и  механиз-
 
      мов передачи.
 
 
 
 
                      1. Системное использование
 
 
 
           Элемент системного использования отражает  абстрактную
 
      структуру данных. В табл. 1  перечислены  структуры  данных
 
      МОС ВП, в табл. 2 - стандартные типы данных.
 
                                                       Таблица 1
 
                 структуры данных МОС ВП
 
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
      Имена_битов_доступа    !  Однородный массив из 32-х
                             !
                             !дескрипторов; каждый дескриптор
                             !
                             !(квадрослово) указывает на имя од-
                             !
                             !ного из 32 разрядов в маске досту-
                             !
                             !па
                             !
      Режим_доступа          !  Байт без знака, обозначающий
                             !
                             !аппаратный режим доступа. Такой
                             !
                             !беззнаковый байт может принимать
                             !
                             !четыре значения: 0 указывает режим
                             !
                             !ядра; 1 - исполнительный режим;
                             !
                             !2 - режим супервизора; 3 - режим


                                - 190 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
                             !пользователя
                             !
      Адрес                  !  Длинное слово без знака,
                             !
                             !обозначающее виртуальный адрес
                             !
                             !памяти для данных или программы,
                             !
                             !но не маски входа процедуры
                             !
                             !(которая имеет тип "процедура")
                             !
      Диапазон_адресов       !  Квадрослово без знака, обозна-
                             !
                             !чающее диапазон виртуальных адре-
                             !
                             !сов области памяти. Первым
                             !
                             !длинным словом задается
                             !
                             !начальный адрес диапазона;
                             !
                             !вторым длинным словом задается
                             !
                             !конечный адрес диапазона
                             !
      Список_аргументов      !  Список параметров процедуры,
                             !
                             !состоящий из одного или
                             !
                             !нескольких длинных слов.
                             !
                             !в первом длинном слове
                             !
                             !находится счетчик - целое число
                             !
                             !без знака, - последовательно
                             !
                             !расположенных, непрерывных
                             !
                             !длинных слов, каждое из которых
                             !
                             !представляет параметр, который
                             !
                             !должен быть передан процедуре
                             !
                             !посредством команды CALL
                             !
      AST_процедура          !  Целое без знака в виде длинного
                             !
                             !слова, указывающее маску входа
                             !


                                - 191 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !процедуры при вызове на уровне
                             !
                             !асинхронных системных прерываний
                             !
                             !(процедуры, которые не должны
                             !
                             !вызываться на уровне асинхронных
                             !
                             !системных прерываний, имеют тип
                             !
                             !"процедура")
                             !
      Булевский              !  Длинное слово без знака,
                             !
                             !обозначающее флаг булевой величи-
                             !
                             !ны, может иметь только два значе-
                             !
                             !ния: 1 (истина) и 0 (ложь)
                             !
      Байт_со_знаком         !  Этот тип данных совпадает
                             !
                             !с типом данных "байт целый (со
                             !
                             !знаком)" (см. Табл. 2)
                             !
      Байт_без_знака         !  Этот тип данных МОС ВП совпадает
                             !
                             !с типом данных "байт (без знака)"
                             !
                             !(см. Табл. 2)
                             !
      Канал                  !  Целое без знака, занимающее
                             !
                             !слово, которое служит индексом
                             !
                             !канала ввода-вывода
                             !
      Символьная_строка      !  Строка, содержания от 0 до 65535
                             !
                             !восьмиразрядных символов. Этот
                             !
                             !тип данных совпадает с типом данных
                             !
                             !"символьная_строка" (см. Табл. 2)
                             !
      Комплексное_число      !  Один из стандартных для системы
                             !
                             !мос вп типов данных комплексных
                             !
                             !чисел с плавающей запятой
                             !
      Значение_условия       !  Целое без знака (длинное слово),


                                - 192 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
                             !указывающее значение
                             !
                             !исключительного состояния
                             !
                             !(то есть состояние при возврате
                             !
                             !либо код системного условия),
                             !
                             !который стандартно возвращается
                             !
                             !процедурой в регистре R0
                             !
      Контекст               !  Длинное слово без знака, которое
                             !
                             !используется вызванной процедурой
                             !
                             !для обслуживания повторяющейся
                             !
                             !последовательности вызовов.
                             !
                             !обычно инициализируется
                             !
                             !вызывающей программой, но
                             !
                             !в последствии обслуживается
                             !
                             !вызванной процедурой
                             !
      Время_дата             !  64-х разрядное целое двоичное
                             !
                             !число без знака, обозначающее
                             !
                             !дату и время в виде числа
                             !
                             !истекших интервалов по 100
                             !
                             !наносеKунд с 00:00 часов 17
                             !
                             !ноября 1858 года. Данный
                             !
                             !тип данных совпадает с
                             !
                             !типом данных "абсолютные
                             !
                             !дата и время" (см. Табл. 2)
                             !
      Имя_устройства         ! Символическая строка, обозначающая
                             !
                             !наименование устройства. Это может
                             !
                             !быть логическое имя, но в этом
                             !


                                - 193 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !случае оно должно быть
                             !
                             !преобразовано в допустимое имя
                             !
                             !устройства
                             !
      Имя_кластера_флага_    !  Символьная строка, обозначающая
                             !
      События                !Имя кластера флага события. Это
                             !
                             !может быть логическое имя,
                             !
                             !которое в таком случае должно
                             !
                             !быть преобразовано в допустимое
                             !
                             !имя кластера флага события
                             !
      Номер_флага_события    !  Целое без знака (длинное слово),
                             !
                             !обозначающее номер флага события
                             !
      Блок_обработчика_выхода!  Структура переменной длины,
                             !
                             !обозначающая блок управления
                             !
                             !обработчика выхода
                             !
      Блок_доступа_файла     !  Структура, обозначающая блок
                             !
      (FAB)                  !доступа к файлу в СУД-32
                             !
      Защита_файла           !  Слово без знака, которое
                             !
      (файл-защита)          !представляет 16-ти разрядную
                             !
                             !маску защиты файла. Маска
                             !
                             !состоит из четырех четырехразрядных
                             !
                             !полей, каждое из которых задает
                             !
                             !защиту, которую следует
                             !
                             !применить при попытке доступа
                             !
                             !к файлу одной из четырех
                             !
                             !категорий пользователей (справа
                             !
                             !налево):
                             !
                             !  1) системные пользователи;


                                - 194 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
                             !  2) владелец файла;
                             !
                             !  3) пользователи с той же
                             !
                             !группой в коде идентификации
                             !
                             !пользователя, что и у владельца;
                             !
                             !  4) все прочие пользователи.
                             !
                             !каждым полем справа налево
                             !
                             !задается по разрядам:
                             !
                             !  1) доступ на удаление;
                             !
                             !  2) доступ на выполнение;
                             !
                             !  3) доступ на запись;
                             !
                             !  4) доступ на чтение.
                             !
                             !установленными в единицу битами
                             !
                             !указывается, какой доступ закрыт
                             !
      Плавающая_запятая      !  Один из стандартных для системы
                             !
      плавающая_точка        !МОС ВП типов данных для чисел с
                             !
                             !плавающей запятой (точкой)
                             !
      Код_функции            !  Длинное слово без знака, указыва-
                             !
                             !ющее операции, которые
                             !
                             !надлежит выполнить процедуре. В
                             !
                             !этом длинном слове есть два поля
                             !
                             !длиной в слово каждое: первое
                             !
                             !поле - это число, задающее
                             !
                             !основную операцию; второе поле -
                             !
                             !это маска или вектор разрядов,
                             !
                             !задающий различные подоперации в
                             !
                             !рамках основной операции
                             !


                                - 195 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
      Блок_состояния_в/в     !  Структура в виде квадрослова,
                             !
                             !содержащая информацию,
                             !
                             !возвращаемую процедурой, которая
                             !
                             !завершает свою работу асинхронно.
                             !
                             !возвращаемая информация меняется
                             !
                             !в зависимости от процедуры
                             !
      Список_об'ектов_2      !  Структура, которая состоит из
                             !
                             !одного или нескольких
                             !
                             !дескрипторов об'ектов и которая
                             !
                             !завершается длинным словом,
                             !
                             !содержащим 0. Каждый дескриптор
                             !
                             !об'екта - это структура из двух
                             !
                             !длинных слов, в которой
                             !
                             !содержится три поля
                             !
      Список_об'ектов_3      !  Структура, которая состоит из
                             !
                             !одного или нескольких
                             !
                             !дескрипторов об'ектов и которая
                             !
                             !завершается длинным словом,
                             !
                             !содержащим 0. Каждый дескриптор
                             !
                             !об'екта - это структура из трех
                             !
                             !длинных слов, в которой
                             !
                             !содержится четыре поля
                             !
      Список_квот_об'ектов   !  Структура, которая содержит один
                             !
                             !или несколько дескрипторов квот
                             !
                             !и которая завершается байтом,
                             !
                             !содержащим значение, которое
                             !
                             !задается символическим именем


                                - 196 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
                             !PQL$_LISTEND. Каждый дескриптор
                             !
                             !квоты представляет имя квоты в
                             !
                             !виде 1 байта, за которым следует
                             !
                             !длинное слово без знака,
                             !
                             !содержащее значение для этой
                             !
                             !квоты
                             !
      Идентификатор_блоки-   !  Целое число без знака в виде
                             !
      ровки                  !длинного слова, обозначающее
                             !
                             !идентификатор блокировки. Такой
                             !
                             !идентификатор присваивается
                             !
                             !средством обслуживания блокировки
                             !
                             !некоторому средству, когда его
                             !
                             !блокирование санкционировано
                             !
      Блок_состояния_бло-    !  Структура, в которую средство
                             !
      кировки                !обслуживания блокировки
                             !
                             !записывает информацию о состоянии
                             !
                             !для блокированного ресурса. Блок
                             !
                             !состояния блокирования всегда
                             !
                             !содержит не менее двух длинных
                             !
                             !слов: первое длинное слово
                             !
                             !содержит код состояния; второе
                             !
                             !слово первого длинного слова
                             !
                             !зарезервировано; а второе длинное
                             !
                             !слово содержит идентификатор
                             !
                             !блокировки
                             !
      Блок_значения_блоки-   !  Блок в 16 байтов, который
                             !


                                - 197 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
      ровки                  !средство обслуживания блокировки
                             !
                             !включает в блок состояния
                             !
                             !блокировки, если пользователь
                             !
                             !этого запросит. Содержимое блока
                             !
                             !значений блокирования задается
                             !
                             !пользователем и не
                             !
                             !интерпретируется средством
                             !
                             !обслуживания блокирования
                             !
      Логическое_имя         !  Символьная строка (от 1 до 255
                             !
                             !символов), которая отождествляет
                             !
                             !логическое имя либо эквивалентное
                             !
                             !имя, с которым следует работать
                             !
                             !средствам системного обслуживания
                             !
                             !логических имен в системе МОС ВП.
                             !
                             !логическим именам, которые
                             !
                             !обозначают конкретные об'екты
                             !
                             !системы МОС ВП, соответствуют их
                             !
                             !собственнные типы, например,
                             !
                             !логическое имя, идентифицирующее
                             !
                             !устройство, обладает типом
                             !
                             !"имя_устройства"
                             !
      Длинное_слово_со_зна-  !  Данный тип данных МОС ВП совпада-
                             !
      ком                    !ет с типом данных "длинное целое
                             !
                             !(со знаком)" (см. табл. 2)
                             !
      Длинное_слово_без_     !  Данный тип данных МОС ВП совпада-
                             !
      знака                  !ет с типом данных "длинное слово
                             !
                             !(без знака)" (см. табл. 2)


                                - 198 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
      Байт_маска             !  Байт без знака, каждый бит кото-
                             !
                             !рого интерпретируется вызванной
                             !
                             !процедурой. О маске также говорят
                             !
                             !как о наборе "флагов" или как о
                             !
                             !"битовой маске"
                             !
      Маска_длинное_слово    !  Длинное слово без знака, каждый
                             !
                             !бит которого интерпретируется выз-
                             !
                             !ванной процедурой. О маске также
                             !
                             !говорят как о наборе "флагов" или
                             !
                             !как о "битовой маске"
                             !
      Маска_квадрослово      !  Квадрослово без знака, каждый бит
                             !
                             !которого интерпетируется вызванной
                             !
                             !процедурой. О маске также говорят
                             !
                             !как о наборе "флагов" или как о
                             !
                             !"битовой маске"
                             !
      Маска_слово            !  Слово без знака, каждый бит кото-
                             !
                             !рого интерпретируется вызванной
                             !
                             !процедурой. О маске также говорят
                             !
                             !как о наборе "флагов" или как о
                             !
                             !"битовой маске"
                             !
      Нуль_аргумент          !  Длинное слово без знака, обозна-
                             !
                             !чающее "пустой параметр". "пустой
                             !
                             !параметр" - это такой параметр,
                             !
                             !единственным назначением которого
                             !
                             !является сохранение места в списке
                             !
                             !параметров
                             !


                                - 199 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
      Октаслово_со_знаком    !  Данный тип данных МОС ВП совпада-
                             !
                             !ет с типом данных "октаслово целое
                             !
                             !(со знаком)" (см. Табл. 2)
                             !
      Октаслово_без_знака    !  Данный тип данных МОС ВП совпада-
                             !
                             !ET с типом данных "октаслово (без
                             !
                             !знака)" (см. Табл. 2)
                             !
      Защита_страницы        !  Длинное слово без знака, задающее
                             !
                             !защиту страницы, которую надлежит
                             !
                             !применить аппаратуре системы мос
                             !
                             !вп. Значения вида защиты задаются
                             !
                             !посредством битов 0-3; биты 4-31
                             !
                             !игнорируются
                             !
      Процедура              !  Длинное слово без знака,
                             !
                             !обозначающее маску входа процедуры,
                             !
                             !которая не должна вызываться на
                             !
                             !уровне асинхронных системных
                             !
                             !прерываний (параметры, задающие
                             !
                             !процедуры, которые следует вызывать
                             !
                             !на уровне асинхронных системных
                             !
                             !прерываний, имеют тип
                             !
                             !"AST_процедура")
                             !
      Идентификатор_процесса !  Целое без знака в виде длинного
                             !
                             !слова, обозначающее идентификатор
                             !
                             !процесса (PID). Такой идентификатор
                             !
                             !процесса присваивается системой
                             !
                             !процессу при его создании
                             !
      Имя_процесса           !  Символьная строка, которой зада-


                                - 200 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
                             !ется имя процесса
                             !
      Квадрослово_со_знаком  !  Данный тип данных МОС ВП совпада-
                             !
                             !ет с типом данных "квадрослово це-
                             !
                             !лое (со знаком)" (см. табл. 2)
                             !
      Квадрослово_без_знака  !  Данный тип данных совпадает с ти-
                             !
                             !пом данных "квадрослово (без зна-
                             !
                             !ка)" (см. табл. 2)
                             !
      Держатель_прав         !  Квадрослово без знака, задаю-
                             !
                             !щее право доступа пользователя
                             !
                             !к об'екту системы. Такое квад-
                             !
                             !рослово содержит два поля:
                             !
                             !первое - это идентификатор в ви-
                             !
                             !де длинного слова без знака
                             !
                             !(тип "идентификатор_прав"),
                             !
                             !второе - это битовая маска
                             !
                             !в виде длинного слова, каждый раз-
                             !
                             !ряд которой задает право доступа
                             !
      Идентификатор_прав     !  Длинное слово без знака,
                             !
                             !обозначающее идентификатор прав,
                             !
                             !которым идентифицируется группа
                             !
                             !интерфейсов в контексте обеспечения
                             !
                             !защиты данных в среде МОС ВП. Такая
                             !
                             !среда прав может содержать все
                             !
                             !части кода идентификации
                             !
                             !пользователя (UIC)
                             !
      Блок_доступа_к_за-     !  Структура, обозначающая блок
                             !


                                - 201 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
      писям                  !доступа к записи в СУД-32
                             !
      Идентифкатор_секции    ! Квадрослово без знака, обозначаю-
                             !
                             !щее идентификатор глобальной сек-
                             !
                             !ции. Такой идентификатор задает
                             !
                             !версию глобальной секции и те
                             !
                             !критерии, которые следует исполь-
                             !
                             !зовать для согласия с данной гло-
                             !
                             !бальной секцией
                             !
      Имя_секции             ! Символьная строка, которая обозна-
                             !
                             !чает имя глобальной секции. Эта
                             !
                             !символьная строка может быть логи-
                             !
                             !ческим именем, но оно должно
                             !
                             !преобразовываться в допустимое имя
                             !
                             !глобальной секции
                             !
      Идентификатор_доступа_ ! Квадрослово без знака, которое
                             !
      системы                !обозначает значение идентификации
                             !
                             !системы, которое должно быть
                             !
                             !связано с базой данных прав
                             !
      Имя_времени            ! Символьная строка, задающая вели-
                             !
                             !чину (отсчет) времени в формате
                             !
                             !системы МОС ВП
                             !
      UIC (кип)              ! Длинное слово без знака, обознача-
                             !
                             !ющее код идентификации пользователя
                             !
                             !(UIC)
                             !
      (Пар_пользователя)     ! Длинное слово без знака,
                             !
                             !обозначающее заданный (определен-
                             !
                             !ный) пользователем параметр. Это


                                - 202 -
 
                           00152-01 97 08
 
 
                                             Продолжение табл. 1
      ----------------------------------------------------------
                             !
      Структура данных       !       Определение
                             !
      -----------------------!----------------------------------
                             !
                             !длинное слово передается процедуре
                             !
                             !в качестве параметра, но содержи-
                             !
                             !мое длинного слова определяется и
                             !
                             !интерпретируется пользователем
                             !
      Переменный_параметр    ! Длинное слово без знака, обознача-
                             !
                             !ющее параметр-переменную. Параметр-
                             !
                             !переменная может иметь переменный
                             !
                             !тип в зависимости от характеристик
                             !
                             !других параметров вызова
                             !
      Вектор_байтов_со_      ! Однородный массив, все элементы
                             !
      знаком                 !которого являются байтами со
                             !
                             !знаком
                             !
      Вектор_байтов_без_     ! Однородный массив, все элементы
                             !
      знака                  !которого являются байтами без
                             !
                             !знака
 
 
                                                        Таблица 2
 
              Стандартные типы данных системы МОС ВП
 
      -----------------------------------------------------------
                                       !
               Тип данных              !     Символьный код
                                       !
      -----------------------------------------------------------
                                       !
        Абсолютные дата и время        !  DSC$K_DTYPE_ADT
                                       !
        Байт, целый (со знаком)        !  DSC$K_DTYPE_B
                                       !
        Значение граничной метки       !  DSC$K_DTYPE_BLV
                                       !
        Граничное значение процедуры   !  DSC$K_DTYPE_BPV
                                       !
        Байт (без знака)               !  DSC$K_DTYPE_BU
                                       !
        Промежуточные временные Кобола !  DSC$K_DTYPE_CIT


                                - 203 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 2
      -----------------------------------------------------------
                                       !
               Тип данных              !     Символьный код
                                       !
      -----------------------------------------------------------
                                       !
        Число с плавающей запятой фор- !  DSC$K_DTYPE_D
                                       !
      мата D                           !
                                       !
        Комплексное  число с плавающей !  DSC$K_DTYPE_DC
                                       !
      запятой формата D                !
                                       !
        Дескриптор                     !  DSC$K_DTYPE_DSC
                                       !
        Число с плавающей запятой фор- !  DSC$K_DTYPE_F
                                       !
      мата F                           !
                                       !
        Комплексное  число с плавающей !  DSC$K_DTYPE_FC
                                       !
      запятой формата F                !
                                       !
        Число с плавающей запятой фор- !  DSC$K_DTYPE_G
                                       !
      мата G                           !
                                       !
        Комплексное  число с плавающей !  DSC$K_DTYPE_GC
                                       !
      запятой формата G                !
                                       !
        Число с плавающей запятой фор- !  DSC$K_DTYPE_H
                                       !
      мата H                           !
                                       !
        Комплексное  число с плавающей !  DSC$K_DTYPE_HC
                                       !
      запятой формата H                !
                                       !
        Длинное целое (со знаком)      !  DSC$K_DTYPE_L
                                       !
        Длинное слово (без знака)      !  DSC$K_DTYPE_LU
                                       !
        Числовая строка, слева отдель- !  DSC$K_DTYPE_NL
                                       !
      ным символом указан знак числа   !
                                       !
        Числовая строка, слева наложе- !  DSC$K_DTYPE_NLO
                                       !
      нием указан знак числа           !
                                       !
        Числовая строка, справа отдель-!  DSC$K_DTYPE_NR
                                       !
      ным символом указан знак числа   !
                                       !
        Числовая строка, справа  нало- !  DSC$K_DTYPE_NRO
                                       !


                                - 204 -
 
                           00152-01 97 08
 
 
                                              Продолжение табл. 2
      -----------------------------------------------------------
                                       !
               Тип данных              !     Мимвольный код
                                       !
      -----------------------------------------------------------
      жением указан знак числа         !
                                       !
        Числовая строка без знака      !  DSC$K_DTYPE_NU
                                       !
        Числовая строка с зоной знака  !  DSC$K_DTYPE_NZ
                                       !
        Октаслово, целоE (со знаком)   !  DSC$K_DTYPE_O
                                       !
        Октаслово (без знака)          !  DSC$K_DTYPE_OU
                                       !
        Упакованная десятичная строка  !  DSC$K_DTYPE_P
                                       !
        Квадрослово, целое (со знаком) !  DSC$K_DTYPE_Q
                                       !
        Квадрослово (без знака)        !  DSC$K_DTYPE_QU
                                       !
        Символьная строка              !  DSC$K_DTPE_T
                                       !
        Выравненная цепочка битов      !  DSC$K_DTYPE_V
                                       !
        Символьная строка переменной   !  DSC$K_DTYPE_VT
                                       !
      длины                            !
                                       !
        Невыравненная цепочка битов    !  DSC$K_DTYPE_VU
                                       !
        Слово, целое (со знаком)       !  DSC$K_DTYPE_W
                                       !
        Слово (без знака)              !  DSC$K_DTYPE_WU
                                       !
        Неопределенный                 !  DSC$K_DTYPE_Z
                                       !
        Маска входа процедуры          !  DSC$K_DTYPE_ZEM
                                       !
        Последовательность инструкций  !  DSC$K_DTYPE_ZI
                                       !
      (команд)                         !
 


                                - 205 -
 
                           00152-01 97 08
 
 
                         2. Механизм доступа
 
 
 
           Точка входа  доступа  к  параметру  описывает  способ,
 
      которым вызванная подпрограмма осуществляет доступ  к  дан-
 
      ным, задаваемым таким  параметром.  Наиболее  общеупотреби-
 
      тельными являются три  способа  доступа  (формальный  пара-
 
      метр - это параметр процедуры с точки зрения вызванной про-
 
      цедуры, а фактический параметр - это параметр  процедуры  с
 
      точки зрения программы, которая вызывает процедуру):
 
           1) только для чтения. Формальным  параметром  является
 
      константа. Соответствующий фактический параметр можно толь-
 
      ко считывать: на него нельзя записать информацию либо изме-
 
      нить его содержимое;
 
           2) только для записи. Формальным  параметром  является
 
      переменная. Значение соответствующего фактического парамет-
 
      ра записывается на место данной переменной вызванной проце-
 
      дурой;
 
           3) для  модификации.  Формальным  параметром  является
 
      переменная. Значение такой переменной записывается програм-
 
      мой, вызывающей процедуру, и может  считываться  или  изме-
 
      няться вызванной процедурой.
 
           Полный перечень типов доступа,  допускаемых  правилами
 
      вызова процедур и обработки условий системы MOC вп, следую-
 
      щий:
 
           1) только для чтения;
 
           2) только для записи;
 
           3) для модификации;
 
           4) вызов функции (перед возвратом);
 
           5) JMP (переход) после раскрутки;
 
           6) вызов после раскрутки стека;


                                - 206 -
 
                           00152-01 97 08
 
 
           7) вызов без раскрутки стека;
 
 
 
 
                   3. Механизмы передачи параметров
 
 
 
           Механизм передачи параметров - это способ, посредством
 
      которого параметр задает ту фактическую информацию, которая
 
      будет использоваться вызыванной  подпрограммой.  Существует
 
      три вида механизмов передачи параметров:
 
           1) посредством  значения.  Если  параметр,  занимающий
 
      длинное слово в  списке  параметров,  содержит  фактические
 
      данные, которые должны использоваться программой,  говорят,
 
      что фактические данные  передаются  программе  "посредством
 
      значения" или "по значению".  Поскольку  параметр  занимает
 
      всего одно длинное слово, посредством значения могут  пере-
 
      даваться только такие данные, которые можно  представить  в
 
      одном длинном слове;
 
           2) посредством  ссылки  (по  адресу).  Если  параметр,
 
      занимающий длинное  слово  в  списке  параметров,  содержит
 
      адрес данных, которые должны использоваться программой,  то
 
      говорят, что данные передаются  "посредством  ссылки"  ("по
 
      ссылке");
 
           3) посредством дескриптора. Если параметр,  занимающий
 
      в списке параметров длинное слово, содержит адрес  дескрип-
 
      тора (описателя), говорят, что данные передаются "посредст-
 
      вом дескриптора" ("по  дескриптору").  Дескриптор  содержит
 
      два или более длинных слов (в зависимости от класса исполь-
 
      зуемого дескриптора), описывающих местонахождение, длину  и
 
      тип данных, которые должны использоваться вызываемой  прог-
 
      раммой.
 


                                - 207 -
 
                           00152-01 97 08
 
 
           На рис. 1 -  3  проиллюстрированы  механизмы  передачи
 
      параметров.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


                                - 208 -
 
                           00152-01 97 08
 
 
                Передача параметра посредством значения
 
      Список параметров
 
      ----------------
      !         !N   ! (AP)-указатель параметров
      ----------------
      !Параметр 1    !
      ----------------
      !Параметр 2    !
      ----------------
      !Фактическое   !
      !              !
      !значение      !
      ----------------
      !       .      !
      !       .      !
      !       .      !
      ----------------
      !Параметр N    !
      ----------------
 
                                Рис. 1
 
 
 
                Передача параметра посредством ссылки
 
      ----------------
      !         !N   ! (AP)-указатель параметров
      ----------------
      !Параметр 1    !
      ----------------
      !Параметр 2    !
      ----------------
      !Указатель     !
      !              !
      !фактического  ! *
      !              !  *
      !значения      !   *                  Данные
      ----------------    *             --------------
      !       .      !     *            !Фактическое !
      !       .      !      ***********>!            !
      !       .      !                  !значение    !
      ----------------                  --------------
      !Параметр N    !
      ----------------
 
                                Рис. 2
 


                                - 209 -
 
                           00152-01 97 08
 
 
                Передача параметра посредством дескриптора
 
                                                   Данные
      ----------------                              -----  а
      !         ! N  ! (AP)-указатель параметров !->! A !  !
      ----------------                           !  -----  !
      !Параметр 1    !                           !  ! B !  !
      ----------------                           !  -----  !
      !Параметр 2    !                           !  ! C !  !
      ----------------                           !  -----  !
      !Указатель     !                           !  ! D ! Длина
      !              !--- ---------------------  !  -----  !
      !дескриптора   !        Дескриптор      !  !  ! E !  !
      ----------------   -------------------  !  !  -----  !
      !       .      !   !Класс!D Тип!Длина!<-!  !  ! F !  !
      !       .      !   -------------------     !  -----  !
      !       .      !   !    Указатель    !------  ! G !  !
      ----------------   -------------------        -----  !
      !Параметр N    !                              ! H !  !
      ----------------                              -----  V
 
                                Рис. 3
 
 
           Примечание. Параметр 1, параметр 2,  параметр  N  (см.
 
      рис.1-3) могут быть переданы посредством  значения,  ссылки
 
      или дескриптора.
 
           В  табл.3  приведены  механизмы  передачи  параметров,
 
      которые допускаются правилами вызова процедур  и  обработки
 
      условий системы МОС ВП.
 
                                                      Таблица 3
 
      Стандартные механизмы передачи параметров системы МОС ВП
 
      ---------------------------------------------------------
                                             !
          Механизм передачи параметров       !  Код дескриптора
                                             !
      ---------------------------------------------------------
                                             !
        Посредством значения                 !
                                             !
        Посредством ссылки                   !
                                             !
        Посредством ссылки, ссылка на массив !
                                             !
      данных                                 !
                                             !
        Посредством дескриптора              !
                                             !
        Посредством дескриптора, фиксирован- !
                                             !
      ная длина                              !   DSC$K_CLASS_S


                                - 210 -
 
                           00152-01 97 08
 
 
                                            Продолжение табл. 3
      ---------------------------------------------------------
                                             !
          Механизм передачи параметров       !  Код дескриптора
                                             !
      ---------------------------------------------------------
                                             !
        Посредством дескриптора, динамическая!
                                             !
      строка                                 !   DSC$K_CLASS_D
                                             !
        Посредством дескриптора, массив      !   DSC$K_CLASS_A
                                             !
        Посредством дескриптора, процедура   !   DSC$K_CLASS_P
                                             !
        Посредством дескриптора, десятичная  !
                                             !
      строка                                 !   DSC$K_CLASS_SD
                                             !
        Посредством дескриптора, массив с    !
                                             !
      разрывами (не сплошной)                !   DSC$K_CLASS_NCA
                                             !
        Посредством дескриптора, строка  пе- !
                                             !
      ременной длины                         !   DSC$K_CLASS_VS
                                             !
        Посредством дескриптора, массив строк!
                                             !
      переменной длины                       !   DSC$K_CLASS_VSA
                                             !
        Посредством дескриптора, не          !
                                             !
      выравненная цепочка битов (разрядов)   !   DSC$K_CLASS_UBS
                                             !
        Посредством дескриптора, не          !
                                             !
      выравненный массив битов (разрядов)    !   DSC$K_CLASS_UBA
                                             !
        Посредством дескриптора, строка с    !
                                             !
      границами                              !   DSC$K_CLASS_SB
                                             !
        Посредством дескриптора, не вырав-   !
                                             !
      ненная  цепочка  битов  (разрядов)  с  !   DSC$K_CLASS_UBSB
                                             !
      границами                              !
 
 
 
 


                                - 211 -
 
                           00152-01 97 08
 
 
                     Перечень ссылочных документов
 
 
 
      1.Oперационная система МОС ВП. Подсистема исполнительной
 
        библиотеки. Программы исполнительной библиотеки. Руковод-
 
        ство программиста. 00152-01 33 09.
 
      2.Oперационная система МОС ВП. Подсистема системного сер-
 
        виса. Программы системного обслуживания. Справочный мате-
 
        риал. 00152-01 97 06.
 
      3.Oперационная система МОС ВП. Подсистема системного сер-
 
        виса. Интерфейсные программы. Руководство программиста.
 
        00152-01 33 02.
 
      4.Oперационная система МОС ВП. Система управления данными.
 
        программирование на языке Макроассемблер. Руководство
 
        программиста. 00152-01 33 07.
 
      5.Oперационная система МОС ВП. Подсистема системного сер-
 
        виса. Системные соглашения. Справочный материал.
 
        00152-01 97 05.
 
      6.Oперационная система МОС ВП. Подсистема взаимодействия
 
        пользователей. Программа терминального взаимодействия.
 
        Руководство оператора. 00152-01 34 05.
 
      7.Oперационная система МОС ВП. Подсистема разработки про-
 
        грамм. Программа компоновщик. Руководство программиста.
 
        00152-01 33 04.
 
 
 
 

                                 - 211K -
     
                           2б.00152-01 97 08
     
     
                     Перечень ссылочных документов
     
     
     
     
      1.Oперационная система МОС ВП. Подсистема исполнительной
     
        библиотеки. Программы исполнительной библиотеки. Руковод-
     
        ство программиста. 2б.00152-01 33 09.
     
      2.Oперационная система МОС ВП. Подсистема системного сер-
     
        виса. Программы системного обслуживания. Справочный мате-
     
        риал. 2б.00152-01 97 06.
     
      3.Oперационная система МОС ВП. Подсистема системного сер-
     
        виса. Интерфейсные программы. Руководство программиста.
     
        2б.00152-01 33 02.
     
      4.Oперационная система МОС ВП. Система управления данными.
     
        программирование на языке Макроассемблер. Руководство
     
        программиста. 2б.00152-01 33 07.
     
      5.Oперационная система МОС ВП. Подсистема системного сер-
     
        виса. Системные соглашения. Справочный материал.
     
        2б.00152-01 97 05.
     
      6.Oперационная система МОС ВП. Подсистема взаимодействия
     
        пользователей. Программа терминального взаимодействия.
     
        Руководство оператора. 2б.00152-01 34 05.
     
      7.Oперационная система МОС ВП. Подсистема разработки про-
     
        грамм. Программа компоновщик. Руководство программиста.
     
        2б.00152-01 33 04.
     
     
     
    

                                - 212 -
 
                           00152-01 97 08
 
 
      8.Oперационная система МОС ВП. Подсистема управления. Про-
 
        грамма пополнения набора системных сообщений. Руководст-
 
        во пользователя. 00152-01 92 10.
 
      9.Oперационная система МОС ВП. Подсистема управления.
 
        использование диалогового командного языка и командных
 
        процедур. Справочный материал. 00152-01 97 04.
 
      10.Oперационная система МОС ВП. Подсистема разработки про-
 
         грамм. Символический отладчик. Руководство оператора.
 
         00152-01 34 07.
 
      11.Oперационная система МОС ВП. Подсистема разработки про-
 
         грамм. Программа установки образов системы. Руководство
 
         пользователя. 00152-01 92 18.
 
      12.Oперационная система МОС ВП. Система программирования
 
         на языке Макроассемблер. Описание языка.
 
         000152-01 35 01.
 
 
 
 
 


                                - 212K -
     
                           2б.00152-01 97 08
     
     
      8.Oперационная система МОС ВП. Подсистема управления. Про-
     
        грамма пополнения набора системных сообщений. Руководст-
     
        во пользователя. 2б.00152-01 92 10.
     
      9.Oперационная система МОС ВП. Подсистема управления.
     
        использование диалогового командного языка и командных
     
        процедур. Справочный материал. 2б.00152-01 97 04.
     
      10.Oперационная система МОС ВП. Подсистема разработки про-
     
         грамм. Символический отладчик. Руководство оператора.
     
         2б.00152-01 34 07.
     
      11.Oперационная система МОС ВП. Подсистема разработки про-
     
         грамм. Программа установки образов системы. Руководство
     
         пользователя. 2б.00152-01 92 18.
     
      12.Oперационная система МОС ВП. Система программирования
     
         на языке Макроассемблер. Описание языка.
     
         2б.000152-01 35 01.
     
     
     
     
     
     

 
                             - 213K -

                         2б.00152-01 97 08

    ----------------------------------------------------------- 
    I               Лист регистрации изменений                I
    ----------------------------------------------------------- 
    I Номера листов (страниц)IВсего I       IВходящийI    I   I
    I------------------------IлистовI    N  I    N   I    IДа-I
    I   IИз- IЗа- I   IАнну- I(стра-I       Iсопрово-IПодпIта I 
    IИзмIме- Iме- IНо-Iлиро- Iниц) вIдокуменIдительноI    I   I
    I   Iнен-Iнен-IвыхIванныхIдокум.I   та  Iго докумI    I   I
    I   Iных Iных I   I      I      I       I и дата I    I   I 
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    -----------------------------------------------------------
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
    I   I    I    I   I      I      I       I        I    I   I
    ----------------------------------------------------------- 
  

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!