ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Часть 7 ОБЗОР БИБЛИОТЕКИ ================ SYSTEM ------ Модуль SYSTEM - это низкоуровневый модуль, содержащий зависящие от компилятора призна- ки, такие как типы данных специального интереса в данной реализации. Некоторые из процедур в этом модуле являются встроенными в компилятор, т.е. код для этих процедур будет вырабаты- ваться подстановкой вместо вызова процедуры. SYSTEM охватывает: - поддержку особенностей процессоров семейства 8086; - поддержку конкурирующих процессов. SYSTEM не проверяет версии остальных модулей. AsmLib ------ AsmLib - вспомогательный модуль, который нет необходимости использовать непосредствен- но; здесь содержатся все различные ассемблерные биты. Некоторые процедуры, которые опреде- лены в других модулях, в действительности находятся в AsmLib. Это достигается средствами концепции алиасов JPI Modula-2 (cм. ГЛАВУ 6). AsmLib использует SYSTEM. MATHLIB ------- MATHLIB реализован на языке Ассемблера. Он охватывает: - тригонометрические и гиперболические функции над данными действительного типа; - логарифмические функции от данных действительного типа; - преобразование действительных в двоично-десятичные; - особенности процессора 8087. Контроль версий MATHLIBа использует SYSTEM. Str --- Модуль Str позволяет обрабатывать строки. Он охватывает: - операции над строками: конкатенация (объединение), добавление в конец, вставка, уда- ление; - сравнение строк; - поиск, сопоставление в строке; - преобразование строки в числовые типы. Str использует AsmLib и MATHLIB. Lib --- Этот модуль содержит комплект полезных процедур. Некоторые части его написаны на Modula-2, другие используются из AsmLib по алиасам. Lib охватывает: - сортировку; - генерацию случайных чисел; - операции с блочной памятью; - длинные переходы; - адресная арифметика; - обработка останова и ошибок; - звуковые процедуры. Lib использует SYSTEM, AsmLib, Str и Storage. Storage ------- Модуль Storage поддерживает динамические области памяти. Он охватывает: - распределение и освобождение памяти; - предоставляет информацию о наличии памяти. Storage использует SYSTEM. Process ------- Этот модуль реализует много-процессное управление с планированием квантования времени и синхронизацией процессов. Process охватывает: - инициирование процессов; - синхронизация средствами семафоров. Process использует SYSTEM, Lib, Storage. Graph ----- Модуль Graph реализует простую графику. Он охватывает: - выбор режимов экрана; - запись и чтение отдельных пикселей; - рисование линий и окружностей; - рисование заполненных окружностей и полигонов. Graph использует SYSTEM, Lib. FIO --- Этот модуль разрешает доступ к файлам MS-DOSа. Вводить/ выводить в файлы можно как не- форматированные двоичные данные, так и форматированные данные в текстовые файлы. Файлы - это обычно дисковые файлы, но могут быть и любым устройством, разрешаемым MS-DOS. FIO охва- тывает: - создание, удаление, переименование, открытие и закрытие файлов; - чтение, запись, установка файлов; - создание, удаление, изменение директории; - просмотр директории; - чтение и запись символов, логических данных, целых, положительных, действительных, строк. FIO использует SYSTEM, AsmLib, Lib, Str. IO -- Модуль IO обеспечивает форматированный ввод/вывод в стандартные входные/выходные уст- ройства (например, экран или клавиатура). Ввод и вывод может быть переназначен. IO также содержит функции для прямого ввода с клавиатуры. IO охватывает: - чтение и запись символов, логических данных, целых, положительных, действительных, строк; - переназначение на любое устройство; - чтение символов непосредственно с клавиатуры; - контроль готовности клавиш. IO использует SYSTEM, Lib, Str, FIO. Window ------ Модуль Window позволяет определить области экрана для вывода. Эти области называются окнами (windows) и могут быть отображены одновременно, возможно, с положением на физическом экране. Window охватывает: - создание, освобождение, открытие, закрытие окон; - установка рамки, цвета, заголовка окна; - изменение размера, положения, уровня окон; - управление курсора внутри окна; - вставка и удаление строк в окнах; - палитра окон; - запись в окна, используя IO модуль. Window использует SYSTEM, AsmLib, Lib, Str, Storage. FloatExc -------- Модуль FloatExc поддерживает обработку особых ситуаций процессора 8087. Он охватывает: - включение/выключение особых ситуаций 8087-процессора. Использует SYSTEM, Lib, MATHLIB, Str. На этом заканчивается общее введение к библиотеке. Более специфичные описания даются в следующих секциях. КАК ПОЛЬЗОВАТЬСЯ БИБЛИОТЕЧНЫМ СПРАВОЧНИКОМ ========================================== Лучше, чем описание процедур в алфавитном порядке, описание отдельных процедур можно найти в модуле, к которому они принадлежат. Список всех процедур можно найти на стр. 252. Читая описание отдельной процедуры, прочтите также и общие замечания в секции, к кото- рой она принадлежит. МОДУЛЬ Str ========== Эта секция связана с функциями обработки строк, которые включают обработку строк и преобразование строк в числа и наоборот. Язык Modula-2 не имеет встроенного типа "строка". Строки реализованы как тип ARRAY [0..N] OF CHAR. Если строковому литералу назначен такой тип, он будет завершен посредством добавления к строке символа CHR(0C). Кстати, это не лучше, если длина строкового литерала равна длине выходной строки. Все процедуры, которые возвращают строку (посредством параметра VAR), будут завершать эту процедуру нулем, пока длина результирующей строки больше или равна длине выходной стро- ки. Также, если длина результирующей строки больше длины выходной строки, результат будет урезаться. ОБЩИЕ СТРОКОВЫЕ ПРОЦЕДУРЫ ========================= Append ------ PROCEDURE Append(VAR R: ARRAY OF CHAR; S: ARRAY OF CHAR); Добавляет строку S в конец строки R. Caps ---- PROCEDURE Caps(VAR S: ARRAY OF CHAR); Обращает буквы нижнего регистра в строке S в буквы верхнего регистра. Compare ------- PROCEDURE Compare(S1,S2: ARRAY OF CHAR) : INTEGER; Сравнивает строки S1 и S2 лексикографически (т.е. она сравнивает символы слева направо пока (возможно) не будет найдена разница). Результат отмечается следующим образом: Значение Условие -1 если S1 меньше S2; 0 если S1 равно S2; 1 если S1 больше S2. Concat ------ PROCEDURE Concat(VAR R: ARRAY OF CHAR; S1,S2: ARRAY OF CHAR); Объединяет S1 и S2 и результат помещает в R. Copy ---- PROCEDURE Copy(VAR R: ARRAY OF CHAR; S: ARRAY OF CHAR); Копирует строку S в R. Length ------ PROCEDURE Length(S:ARRAY OF CHAR) : CARDINAL; Возвращает длину строки S, не включая завершающий "0", если он присутствует. Pos --- PROCEDURE Pos(S,P: ARRAY OF CHAR) : CARDINAL; Возвращает позицию (начиная от 0) первого появления подстроки P в строке S. Если P не найдена в S, результатом будет MAX(CARDINAL). Slice ----- PROCEDURE Slice(VAR R : ARRAY OF CHAR; S : ARRAY OF CHAR; P, L: CARDINAL); R назначается вырезка из строки S от позиции P до P+L-1. Если P+L-1 больше длины стро- ки S, R назначается вырезка от P до длины S. Если P больше длины S или L равно 0, тогда R становится нулевой строкой (т.е. строка длиной 0). Item ---- PROCEDURE Item(VAR R : ARRAY OF CHAR; S : ARRAY OF CHAR; T : CHARSET; N : CARDINAL); Предполагает, что строка S разделена на (не пустые) подстроки, которые разделены эле- ментами из множества T. Item возвращает N-ную из этих подстрок, считая с 0. Результат пос- тупает в R. Пример: следующий вызов Item s1 := 'aa bb,cc dd'; Item(s2,s1,CHARSET{' ',','},2); присвоит s2 значение "сс". ItemS ----- PROCEDURE ItemS(VAR R : ARRAY OF CHAR; S : ARRAY OF CHAR; T : ARRAY OF CHAR; N : CARDINAL); Эта процедура работает, как Item. Единственное различие состоит в том, что в ItemS разделители, поставляемые Т, определены как ARRAY OF CHAR, в противоположность CHARSET в Item. Insert ------ PROCEDURE Insert( VAR R : ARRAY OF CHAR; S : ARRAY OF CHAR; P : CARDINAL); Вставляет строку S в строку R на позицию Р. Если Р больше, чем Length(R) (длина стро- ки), то S вставляется на позицию, определенную как Length(R). Пример: s2 := "abcdefg"; Insert(s1,"xyz",3); Результатом в s1 становится "abcxyzdefg". Delete ------ PROCEDURE Delete(VAR R: ARRAY OF CHAR; P,L: CARDINAL); Удаляет последовательность L символов в строке R, начиная от Р. Удаление не происхо- дит, если Р больше, чем Length(R). Match ----- PROCEDURE Match(Source,Pattern: ARRAY OF CHAR) : BOOLEAN; Возвращает TRUE, если строка Source совпадает со строкой Pattern. Pattern (образец) может содержать любое количество шаблонных символов '*' и '?'. Символ '?' совпадает с любым одиночным символом, '*' совпадает с любой последовательностью символов (включая последова- тельность нулевой длины). Пример: строка '*m?t*i*' совпадает с 'Automatic'. ПРОЦЕДУРЫ ПРЕОБРАЗОВАНИЙ ======================== Эта секция описывает процедуры для преобразования чисел в строки и обратно. Строка, которая представляет число, может начинаться со знака ("+" или "-"), хотя "-" не разрешен для чисел CARDINAL (целые положительные). Ни начальные, ни конечные пробелы не разрешены в строке. Строка, получаемая в результате преобразования, будет содержать знак, только если чис- ло отрицательное; строка не содержит начальных или конечных пробелов. Все процедуры преобразования имеют логический параметр результата ОК, который устанав- ливается в TRUE, если преобразование успешно, и в FALSE в противном случае. Процедуры, осуществляющие преобразование между строками и числами типа INTEGER/CARDINAL, получают параметр Base, который обозначает основание системы счисления в преобразовании (обычно 10). Base должен иметь значение в пределах от 2 до 16. Шестнадцате- ричные буквы "А"..."F" используются в числах, если Base больше, чем 10. Н не добавляется к 16-ным числам. IntToStr -------- PROCEDURE IntToStr( V : LONGCARD; VAR S : ARRAY OF CHAR; Base : CARDINAL; VAR OK : BOOLEAN); Преобразует значение V типа LONGINT в строковое представление. ОК получает значение FALSE, если строка S слишком коротка, чтобы вместить преобразованное значение. CardToStr --------- PROCEDURE CardToStr( V : LONGINT; VAR S : ARRAY OF CHAR; Base : CARDINAL; VAR OK : BOOLEAN); Преобразует значение V типа CARDINAL в строковое представление. ОК устанавливается в FALSE, если слишком коротка, чтобы вместить преобразованное значение. RealToStr --------- PROCEDURE RealToStr( V : LONGREAL; Precision : CARDINAL; Eng : BOOLEAN; VAR S : ARRAY OF CHAR; VAR OK : BOOLEAN); Производит строковое представление значения V типа LONGREAL. Precision определяет чис- ло цифр, которое вы хотите, чтобы было в мантиссе, и должен лежать в пределах от 1 до 17 (если он выходит за эти пределы, то будет округлен до ближайшей границы). Инженерная нота- ция используется, если Eng имеет значение TRUE, т.е. экспонента представляется как множест- во из трех. Если Eng - FALSE, мантисса представляется с одной значащей цифрой перед деся- тичной точкой (см. пример ниже). ОК имеет значение FALSE, если строка S слишком коротка, чтобы вместить представление V. Пример: Вызов Результат в S RealToStr(123.45,7,FALSE,S,b) '1.234500E+2' RealToStr(0.12345,7,FALSE,S,b) '1.234500E-1' RealToStr(0.12345,7,TRUE,S,b) '123.4500E-3' FixRealToStr ------------ PROCEDURE FixRealToStr( V : LONGREAL; Precision : CARDINAL; VAR S : ARRAY OF CHAR; VAR OK : BOOLEAN); Производит строковое представление значения V типа LONGREAL. Экспонента не дается в этом формате (см. RealToStr). Precision обозначает число цифр после десятичной точки. OK - FALSE, если строка S слишком коротка, чтобы вместить представление V или если ABS(V) боль- ше, чем 1.0Е1. Пример: Вызов Результат в S FixRealToStr(0.12345,7,S,b) '0.1234500' FixRealToStr(123.4567,5,S,b) '123.45670' FixRealToStr(123.4567,2,S,b) '123.46' StrToInt -------- PROCEDURE StrToInt( S : ARRAY OF CHAR; Base : CARDINAL; VAR OK : BOOLEAN ) : LONGINT; StrToInt получает строку S, изображающую значение типа INTEGER, и возвращает соответс- твующее значение типа LONGINT. Base обозначает основание системы счисления, используемой в преобразовании, и должно лежать в пределах от 2 до 16. ОК устанавливается в FALSE, если строка S не представляет из себя значение типа LONGINT. StrToCard --------- PROCEDURE StrToCard( S : ARAAY OF CHAR; Base : CARDINAL; VAR OK : BOOLEAN ) : LONGCARD; StrToCard получает строку S, представляющую целое положительное значение, и возвращает его представление типа LONGCARD. Base обозначает основание системы счисления и должна ле- жать в пределах от 2 до 16. ОК устанавливается в FALSE, если S не представляет значение ти- па LONGCARD. StrToReal --------- PROCEDURE StrToReal( S : ARRAY OF CHAR; VAR OK : BOOLEAN ) : LONGREAL; StrToReal получает строку S, представляющую действительное значение, и возвращает со- ответствующее значение типа LONGREAL. Синтаксис для правильных значений типа LONGREAL можно найти в ГЛАВЕ 6. ОК устанавливается в FALSE, если S не представляет действительное значе- ние. МОДУЛЬ Lib ========== Модуль Lib содержит множество процедур общего назначения. Сортировка ---------- JPI Modula-2 содержит 2 различные процедуры сортировки, которые реализуют quick-sort (быстрая сортировка) и heap-sort (динамическая сортировка) алгоритмы. Быстрая сортировка обычно наискорейшая, но может быть медленной в худшем случае (когда элементы уже отсортиро- ваны). Время выполнения динамической сортировки имеет очень небольшие колебания. Быстрая сортировка имеет стабильный сортировочный алгоритм, т.е. равные ключи не переставляются, в то время как динамическая сортировка нестабильна. QSort ----- TYPE CompareProc = PROCEDURE(CARDINAL, CARDINAL): BOOLEAN; SwapProc = PROCEDURE(CARDINAL, CARDINAL); PROCEDURE QSort(N: CARDINAL; Less: CompareProc; Swap: SwapProc); Qsort осуществляет быструю сортировку. Число элементов задается параметром N. Элементы нумеруются от 1 до N. Параметр Less - это процедура-функция, которая получает 2 параметра типа CARDINAL, если элемент, определенный первым параметром, меньше, чем элемент, опреде- ленный вторым параметром. Swap используется для того, чтобы поменять местами 2 элемента, определенных параметрами. Пример: MODULE SortArray; (* Этот модуль сортирует массив. *) IMPORT Lib; VAR a : ARRAY [1..100] OF CARDINAL; PROCEDURE less(i1,i2 : CARDINAL) : BOOLEAN; BEGIN RETURN a[i1] < a[i2]; END less; PROCEDURE swap(i1,i2 : CARDINAL); VAR tmp : CARDINAL; BEGIN tmp := a[i1]; a[i1] := a[i2]; a[i2] := tmp; END swap; BEGIN GetValues(a); (* назначает значение a. *) Lib.QSort(100,less,swap); (* сортирует массив a. *) END SortArray. HSort ----- PROCEDURE HSort(N: CARDINAL; Less: CompareProc; Swap: SwapProc); HSort реализует динамическую сортировку. Для объяснения параметров см. QSort. ГЕНЕРАЦИЯ СЛУЧАЙНЫХ ЧИСЕЛ ========================= Randomize --------- PROCEDURE RANDOMIZE; Инициирует генератор псевдо-случайных чисел и может быть вызвана перед тем, как вы начнете вызывать процедуры RANDOM или RAND (в противном случае "случайное" поведение вашей программы будет одинаковым всякий раз, когда программа будет выполняться). Random ------ PROCEDURE RANDOM(Range: CARDINAL) : CARDINAL; Возвращает случайное число типа CARDINAL в диапазоне от 0 до Range-1. Rand ---- PROCEDURE RAND() : REAL; Возвращает случайное действительное число в диапазоне: 0.0<= результат <1.0. Процедуры среды --------------- Получить доступ к командной строке ДОСа можно через переменную-указатель СommandLine или через процедуры ParamStr и ParamCount. TYPE CommandType = POINTER TO ARRAY[0..126] OF CHAR; VAR CommandLine : CommandType; Процедуры, описанные ниже, позволят вам получить доступ к среде ДОС и к командной строке. Environment ----------- PROCEDURE Environment(N : CARDINAL) : CommandType; Возвращает строку номер N из среды ДОС. 1-ая строка имеет номер 0. ParamCount ---------- PROCEDURE ParamCount() : CARDINAL; Возвращает число аргументов в командной строке. ParamStr -------- PROCEDURE ParamStr(VAR S: ARRAY OF CHAR; N: CARDINAL); Возвращает аргумент номер N из командной строки в строку S. 1-й аргумент имеет номер один. Операции над блоками памяти --------------------------- Все процедуры в этой секции выполняют некоторые операции над последовательным блоком памяти. Move ---- PROCEDURE Move(Source,Dest: ADDRESS; Count: CARDINAL); Копирует блок размером Count байтов из области памяти, указанной Sourse, в область па- мяти Dest. Направление копирования выбирается так, что перекрывающиеся блоки копируются правильно. WordMove -------- PROCEDURE WordMove(Sourse,Dest: ADDRESS; WordCount: CARDINAL); Аналогично Move, за исключением того, что WordCount обозначает число слов (2 байта), которые надо переместить, а не число байтов. Эта процедура работает быстрее, чем Move с размером, вдвое большим. Fill ---- PROCEDURE Fill(Dest: ADDRESS; Count: CARDINAL; Value: BYTE); Сохраняет Value в Count последовательных байтах, начиная от Dest. WordFill -------- PROCEDURE WordFill( Dest : ADDRESS; WordCount : CARDINAL; Value : WORD); Сохраняет Value в Count последовательных слов, начиная от Dest. ScanR ----- PROCEDURE ScanR( Dest : ADDRESS; Count : CARDINAL; Value : BYTE) : CARDINAL; ScanR осуществляет поиск первого появления значения Value в блоке, начиная от Dest и двигаясь вперед к высшим адресам на Count байтов. Возвращает позицию по отношению к Dest или Count, если Value не найдено. Примеры: Вызов возвращаемое значение ScanR(ADR('klmnoprst'),10,SHORTCARD('p')) 5 ScanR(ADR('klmnoprst'),10,SHORTCARD('k')) 0 ScanR(ADR('klmnoprst'),10,SHORTCARD('x')) 10 ScanL ----- PROCEDURE ScanL( Dest : ADDRESS; Count : CARDINAL; Value : BYTE) : CARDINAL; Работает, как и ScanR, за исключением того, что поиск начинается от Dest и осуществля- ется по направлению к нижним адресам (возвращается все же положительное значение смещения от Dest). ScanNeR ------- PROCEDURE ScanNeR( Dest : ADDRESS; Count : CARDINAL; Value : BYTE) : CARDINAL; Просматривает блок, заданный Dest, идя на Count байтов вперед к верхним адресам до первой позиции, где содержание отличается от Value. Возвращает Count, если каждый элемент в блоке равен Value. Пример: ScanNeR(ADR('aaaaabbbcc'),10,SHORTCARD('a')) возвращает 5 ScanNeL ------- PROCEDURE ScanNeL( Dest : ADDRESS; Count : CARDINAL; Value : BYTE) : CARDINAL; Аналогична ScanNeR, за исключением того, что поиск начинается от Dest в направлении к нижним адресам. Compare ------- PROCEDURE Compare( Source,Dest : ADDRESS; Len : CARDINAL) : CARDINAL; Сравнивает 2 блока, заданных Source и Dest, до первой позиции, где обнаруживается раз- личие. Len обозначает длину поиска. Compare возвращает Len, если 2 блока равны. Процедуры ДОС ------------- Dos --- PROCEDURE Dos(VAR R: SYSTEM.Registers); Позволяет осуществлять вызов любой функции ДОСа (прерывание 21 H). Справьтесь в доку- ментации по ДОСу о подробностях вызова различных функций. Также посмотрите стр. 195 по опи- санию SYSTEM.Registers. Пример: VAR r : SYSTEM.Registers; BEGIN r.AH := 2CH; (* AH - номер вызова функции ДОСа *) Dos(r); (* теперь r.DX:r.CX содержат время *) (* как описано в документации по ДОСу *) END; Intr ---- PROCEDURE Intr(VAR R: SYSTEM.Registers; I: CARDINAL); Позволяет делать программное прерывание, где I - номер прерывания. Справьтесь в доку- ментации по ДОС о деталях прерываний. Также см. стр. 195 по описанию SYSTEM.Registers. Execute ------- PROCEDURE Execute (Name : ARRAY OF CHAR; (* полное имя программы *) CommandLine : ARRAY OF CHAR; (* командная строка для программы *) StoreAddr : ADDRESS; (* область памяти для выполнения *) StoreLen : CARDINAL) (* длина в блоках *) : CARDINAL; (* ответ ДОСа (0-успешное завершение) *) Выполняет программу. Name - полное имя (включая расширение) программы, которую вы хо- тите выполнить. CommandLine содержит параметры (если имеются). Вы должны также определить указатель на область памяти, в которой программа может быть выполнена, и длину этой области в блоках. Эта память может быть распределена функцией ALLOCATE (см. "Модуль STORAGE"). Execute возвращает ответ ДОСа. "0" означает, что программа выполнена, для остальных значений - справьтесь в документации по ДОСу. Вновь стартуемая программа наследует копию среды порождающей программы. Она также наследует все открытые файлы порождающей программы. Пример: MODULE h; IMPORT IO, Lib; VAR s : ARRAY [0..30] OF CHAR; BEGIN Lib.ParamStr(s,1); IO.WrStr('Hello '); IO.WrStr(s); END h. Откомпилируйте и скомпонуйте h.mod для получения h.exe; теперь h.exe может быть выпол- нена из следующей программы, MODULE ExecEx; (* Пример Execute *) IMPORT Storage, Lib, IO; VAR a : ADDRESS; i : CARDINAL; BEGIN Storage.ALLOCATE(a,20000); i :=Lib.Execute("h.exe"," there",a,20000 DIV 16); IF i#0 THEN IO.WrStr('Failed'); END; Storage.DEALLOCATE(a,20000); END ExecEx. которая произведет следующий вывод: Hello there Адресная арифметика ------------------- Процедуры в этой секции выполняют арифметические операции (сложение и вычитание) над указателями. В процессорах 8086 адреса состоят из сегментной части и смещения; физический адрес высчитывается как сегмент * 16 + смещение. Нормализованный указатель - это указатель со смещением в пределах от 0 до 15. AddAddr ------- PROCEDURE AddAddr(A: ADDRESS; increment:CARDINAL): ADDRESS; Возвращает нормализованный адрес байта, расположенного после физического адреса А на число байтов, определенных параметром increment. SubAddr ------- PROCEDURE SubAddr(A: ADDRESS; decrement: CARDINAL): ADDRESS; Возвращает нормализованный адрес байта, расположенного перед физическим адресом А на число байтов decrement. IncAddr ------- PROCEDURE IncAddr(VAR A : ADDRESS; increment: CARDINAL); А становится нормализованным адресом байта, расположенного на increment байтов после физического адреса А. DecAddr ------- PROCEDURE DecAddr(VAR A : ADDRESS; decrement: CARDINAL); А становится нормализованным адресом байта, расположенного на decrement байтов перед физическим адресом А. Длинные переходы ---------------- Длинные переходы - это (ограниченная) возможность сделать нелокальный переход, т.е. длинным переходом выполнение может быть передано от одной процедуры другой, без возврата. Эти процедуры используются при работе с ошибочными ситуациями. SetJmp и LongJmp ---------------- TYPE LongLabel = ARRAY[0..3] OF CARDINAL; PROCEDURE SetJmp(VAR Lbl: LongLabel):CARDINAL; PROCEDURE LongJmp(VAR Lbl: LongLabel; result: CARDINAL); SetJmp сохраняет состояние процедуры в буфере Lbl и возвращает значение 0. Позже вызов LongJmp с тем же буфером восстановит это состояние таким образом, что SetJmp возвратит зна- чение result. SetJmp должен быть вызван перед вызовом LongJmp, и процедура, которая вызвала SetJmp, должна быть активна в момент вызова LongJmp, в противном случае результат непредсказуем. Обратите внимание, что локальные переменные часто содержатся в машинных регистрах (да- же во время вызова процедур), что означает, что их значения могли быть изменены, когда SetJmp "возвращается" через LongJmp. Чтобы обойти эту проблему, для этих локальных перемен- ных может быть испльзована директива компилятора volatile (*$W+*) (см. ГЛАВУ 7). Пример: MODULE LongJmpEx; IMPORT IO,Lib; VAR buf : Lib.LongLabel; PROCEDURE p2; FORWARD; PROCEDURE p; BEGIN IF Lib.SetJmp(buf) # 0 THEN IO.WrStr('LongJmp has been called'); HALT; END; IO.Str('Hello'); IO.WrLn; p2; END p; PROCEDURE p2; VAR error : BOOLEAN; BEGIN error := TRUE; IF error THEN Lib.LongJmp(buf,1); END; END p2; BEGIN p; END LongJmpEx. Будет произведен следующий вывод: Hello LongJmp has been called Обработка ошибок ---------------- MathError --------- PROCEDURE MathError ( R: LONGREAL; S: ARRAY OF CHAR); PROCEDURE MathError2(R1,R2: LONGREAL; S: ARRAY OF CHAR); Процедуры математических ошибок по умолчанию, которые вызываются из некоторых процедур в модуле MATHLIB в случае ошибочного аргумента. Процедуры MathError выводят сообщение, включающее имя ошибочной процедуры (см. " Обработка ошибок" для детального описания). UserBreak --------- PROCEDURE UserBreak; Аварийно завершает программу с сообщением об ошибке выполнения и завершается вызовом процедуры HALT (см. ГЛАВУ 6). Сообщение об ошибке выполнения имеет формат: Run Time Error [AAAA/SSSS:OOOO] User Break AAAA - абсолютный сегмент останова пользователя; SSSS - относительный сегмент (который можно посмотреть в карте компоновки); OOOO - смещение останова пользователя. DisableBreakCheck ----------------- PROCEDURE DisableBreakCheck; Выключает обработку комбинации "УПР-СТОП" (Control-Break). После вызова этой процедуры программа не может быть аварийно завершена нажатием клавиш "УПР-СТОП". По умолчанию провер- ка "УПР-СТОП" включена. Обратите внимание, что "УПР-СТОП" управляется также директивой ком- пилятора (*$B *) (см. ГЛАВУ 7). EnableBreakCheck ---------------- PROCEDURE EnableBreakCheck; Включает обработку "УПР-СТОП" так, что программа может быть аварийно завершена нажати- ем клавиш "УПР-СТОП". Когда программа аварийно завершена, выдается сообщение об ошибке вы- полнения, и программа завершается обращением к процедуре HALT (см. ГЛАВУ 6). Сообщение об ошибке выполнения имеет формат, как описано в UserBreak (см. выше). Кста- ти, если AAAA за пределами программы (например, если она аварийно завершена во время выпол- нения функции ДОСа), сообщение об ошибке выполнения будет иметь форму: Run Time Error [AAAA:OOOO] User Break FatalError ---------- PROCEDURE FatalError(S : ARRAY OF CHAR); Записывает строку S на стандартном устройстве вывода и завершает программу обращением к процедуре HALT. SetReturnCode ------------- PROCEDURE SetReturnCode(code: SHORTCARD); Устанавливает код возврата для использования, когда программа завершена. Это значение передается породившей программе. Если программа была запущена с командной строки, доступ к коду возврата может быть осуществлен через ErrorLevel операционной системы. ДРУГИЕ ПРОЦЕДУРЫ ================ Delay ----- PROCEDURE Delay(Time : CARDINAL); Задерживает выполнение программы на время Time в миллисекундах. Sound ----- PROCEDURE Sound(FreqHz : CARDINAL); Включает звук громкоговорителя компьютера на частоте FreqHz в герцах. NoSound ------- PROCEDURE NoSound; Отключает громкоговоритель. HashString ---------- PROCEDURE HashString( S : ARRAY OF CHAR; Range : CARDINAL) : CARDINAL; HashString высчитывает хеш-значения в пределах от 0 до Range-1 строки S. Terminate --------- PROCEDURE Terminate(P : PROC; VAR C : PROC); Terminate используется для совершения действий, необходимых, когда программа заверша- ется. Terminate производит вызов процедуры Р из процедуры HALT, или когда программа завер- шается. С - это процедура, которая прежде должна быть вызвана процедурой HALT. Обычно про- цедура Р вызывает процедуру С и таким образом строится цепь процедур. Если HALT вызывается в завершающей процедуре, выполнение программы останавливается. Пример: MODULE TerminateEx; IMPORT Lib,IO; VAR Continue1 : PROC; Continue2 : PROC; PROCEDURE CloseDown1; BEGIN IO.WrStr('CloseDown-1'); IO.WrLn; Continue1; END CloseDown1; PROCEDURE CloseDown2; BEGIN IO.WrStr('CloseDown-2'); IO.WrLn; Continue2; End CloseDown2; BEGIN IO.WrStr('Program starts'); IO.WrLn; Lib.Terminate(CloseDown1,Continue1); Lib.Terminate(CloseDown2,Continue2); HALT; IO.WrStr('this statement is never executed'); END TerminateEx. Эта программа производит следующий вывод: Program starts CloseDown-2 CloseDown-1 МОДУЛЬ Storage ============== Эта секция описывает функции обработки памяти, которые позволяют вам распределить и освободить блоки памяти динамически в динамической области. Программы, импортирующие модуль Storage, получают, по умолчанию, динамическую область памяти, называемую главной, но ос- тальные области могут быть определены. Глобальные переменные в модуле Storage -------------------------------------- TYPE HeapRecPtr = POINTER TO HeapRec; HeapRec = RECORD size : CARDINAL; next : HeapRecPtr; END; VAR MainHeap : HeapRecPtr; ClearOnAllocate : BOOLEAN; MainHeap - это заранее определенная по умолчанию главная динамическая область и может быть использована в обращениях к неглавным процедурам памяти. ClearOnAllocate показывает, обнуляет ли процедура ALLOCATE распеределяемый блок памяти. По умолчанию значение ClearOnAllocate - FALSE (см. также директиву компилятора (*$Z*) в ГЛАВЕ 7). Основные процедуры над динамической областью -------------------------------------------- Процедуры ALLOCATE, DEALLOCATE и Available работают с главной динамической областью и потому не нуждаются в ссылках на динамическую память. ALLOCATE -------- PROCEDURE ALLOCATE(VAR a: ADDRESS; size: CARDINAL); Распределяет блок размером size байтов в главной динамической области. Ссылка на расп- ределенный блок возвращается в переменной а. Блок обнуляется, если глобальная переменная ClearOnEntry имеет значение TRUE. Если распределение не удалось, выдается сообщение об ошибке "Heap overflow" ("Переполнение динамической области"), и выполнение программы завер- шается. Максимальный размер блока, который может быть распределен процедурой ALLOCATE сос- тавляет 64К байт; большие блоки могут быть распределены общей динамической процедурой HeapAllocate. DEALLOCATE ---------- PROCEDURE DEALLOCATE (VAR a: ADDRESS; size: CARDINAL); Освобождает блок памяти размером size байтов, указанный адресом a; а потом получает значение NIL. Освобожденный блок становится частью свободной памяти главной динамической области. Available --------- PROCEDURE Available(size : CARDINAL) : BOOLEAN; Возвращает TRUE, если блок размером size байтов может быть распределен из главной ди- намической области. Общие процедуры над динамической памятью ---------------------------------------- MakeHeap -------- PROCEDURE MakeHeap(Source : CARDINAL; (* базовый сегмент динамической области *) Size : CARDINAL (* размер в блоках *) ) : HeapRecPtr; Определяет новую динамическую область. Source дает сегмент памяти, где новая динами- ческая область расположена и должна быть распределена, например, процедурой распределения (ALLOCATE). size - размер в блоках (16 байтов) предоставляемой памяти. MakeHeap возвращает указатель на новую динамическую область. Этот указатель может быть впоследствии использован в обращениях к общим динамическим процедурам: HeapAllocate, HeapDeallocate и т.д. HeapAllocate ------------ PROCEDURE HeapAllocate (Source : HeapRecPtr; (* исходная область *) VAR A : ADDRESS; (* результат *) Size : CARDINAL); (* размер в блоках *) Распределяет блок размером (16 * size) байтов в динамической области, подаваемой пара- метром Source. Указатель на распределенный блок возвращается переменной А. Если распределе- ние не удалось, выдается сообщение об ошибке "Heap overflow" ("Переполнение области"), и выполнение программы завершается. HeapDeallocate -------------- PROCEDURE HeapDeallocate (Source: HeapRecPtr; (* исходная область *) VAR A : ADDRESS; (* освобождаемый блок *) Size : CARDINAL); (* размер в блоках *) Освобождает блок памяти размером в (16 * size) байтов, начиная от адреса А, в области, указанной Source; A затем устанавливается в NIL. Освобожденный блок становится частью сво- бодной памяти динамической области. Обратите внимание, что вы должны всегда освобождать блок из той же динамической области, из которой он был распределен. HeapAvail --------- PROCEDURE HeapAvail(Source : HeapRecPtr) : CARDINAL; Возвращает размер в параграфах (по 16К) наибольшего блока, доступного для распределе- ния из динамической области Source. HeapTotalAvail -------------- PROCEDURE HeapTotalAvail(Source : HeapRecPtr):CARDINAL; Возвращает размер в параграфах общего размера памяти, доступногог для распределения из области Source. HeapChangeSize -------------- PROCEDURE HeapChangeSize (Source : HeapRecPtr; (* исходная область *) VAR A : ADDRESS; (* блок для изменения *) OldSize, (* старый размер блока *) NewSize : CARDINAL); (* новый размер в параг- рафах *) Изменяет размер блока, указанного А. OldSize и NewSize - размеры в параграфах сущест- вующего и желаемого блоков. Source указывает динамическую область, на которой распределен блок. HeapChangeSize делает недействительным любое копирование блока, если это возможно, но он может быть перемещен, если изменить А. HeapChangeAlloc --------------- PROCEDURE HeapChangeAlloc (Source : HeapRecPtr; (* исходная область *) A : ADDRESS; (* блок, который надо изменить*) OldSize, (* старый размер блока *) NewSize : CARDINAL (* новый размер блока *) ) : BOOLEAN; (* если успешно *) Пытается изменить размер блока А, распределенного на области Source. OldSize и NewSize - размеры в параграфах существующего и желаемого блоков. Возвращает TRUE, если завершен ус- пешно (только увеличение может отсутствовать). Если нет, то действия не производятся. Обра- тите внимание, что эта процедура никогда не перемещает блок, в противоположность процедуре HeapChangeSize. |