|
Часть 8
МОДУЛЬ SYSTEM
==============
Модуль SYSTEM играет особую роль в компиляторе JPI Modula-2, т.к. содержит зависящие
от компилятора характеристики (а именно Ofs и Seg). Действительно, некоторые процедуры яв-
ляются встроенными в компилятор, поэтому модуль также называется pseudo module (псевдо мо-
дуль).
SYSTEM также содержит типы данных, которые представляют интерес в этом конкретном при-
менении.
TYPE
PROCESS = ADDRESS;
Registers = RECORD
CASE : BOOLEAN OF
| TRUE : AX,BX,CX,DX,BP,SI,DI,DS,ES: CARDINAL;
Flags : BITSET;
| FALSE : AL,AH,BL,BH,CL,CH,DL,DH : SHORTCARD;
END;
END;
CONST
CarryFlag = 0;
ZeroFlag = 6;
VAR
HeapBase : CARDINAL ;
(* Базовый сегмент динамической области *)
Тип Registers используется при выдаче запросов ДОСа и в прерываниях, т.к. доступ к
внутренним регистрам процессора необходим при осуществлении этих действий.
Тип PROCESS объясняется ниже.
Низкоуровневые процессы
-----------------------
Т.к. IBM PC/AT (и сравнимые с ним) являются компилятором с единственным процессором,
действительно одновременные процессы не могут быть реализованы посредством сопрограмм.
Сопрограмма - это последовательная программа, которая может быть приостановлена путем
передачи выполнения другой сопрограмме (которая будет возобновлена с того места, в котором
она была раньше приостановлена). Когда сопрограмма приостанавливается, ее текущее состояние
сохраняется; таким образом, что она может возобновить свое выполнение позже, когда другая
сопрограмма передаст выполнение обратно данной сопрограмме.
В дальнейшем мы будем использовать термин процесс вместо сопрограммы.
Система приоритетов модулей в JPI Мodula-2
------------------------------------------
Система приоритетов модулей управляет обработкой аппаратных прерываний. Система прио-
ритетов основана на контроллере аппаратных прерываний в компьютере РС/АТ. Приоритет интерп-
ретируется как маска (BITSET-установка бита), который разрешает/запрещает отдельные преры-
вания. Прерывание запрещено, если его соответствующий бит в маске установлен в 1. Чтобы
использовать систему приоритетов, требуются некоторые знания о контроллере прерываний (см.
"Технические ссылки"). На входе блока (тело PROCEDURE или тело MODULE), который имеет прио-
ритет маски в контроллере прерываний и приоритет для блока, которые логически объединяются
вместе; на выходе из блока маска в контроллере прерываний восстанавливается в то состояние,
которое она имела на входе блока.
АТ и РС отличаются тем, что АТ имеет 2 контроллера прерываний, а РС - только 1, т.к.
АТ использует все 16 бит маски приоритета; 8 младших бит используются для установки маски в
первичном контроллере прерываний, старшие 8 бит используются для установки главного конт-
роллера. В случае РС только младшие 8 бит используются для установки маски в контроллере
прерываний.
Маска в контроллере прерываний считается частью состояния процесса; таким образом, она
сохраняется и восстанавливается операциями TRANSFER и IOTRANSFER (см. процедуры ниже).
Если IOTRANSFER связана с аппаратным прерыванием, обрабатываемым контроллером прерыва-
ний, выдается неопределенный End-Of-Interrupt (конец прерывания).
Запросы прерываний (IRQs), обрабатываемые аппаратурой, классифицированы через вектора
прерываний от 08Н до 0FH для первичного контроллера и от 70Н до 77Н для главного контролле-
ра. Это соответствует запросам прерываний от IRQ 0 - IRQ 15.
Пример обработки прерывания:
MODULE T;
FROM SYSTEM IMPORT NEWPROCESS, IOTRANSFER, TRANSFER,
CurrentPriority, NewPriority,
ADRESS;
VAR IntProc : ADDRESS;
MODULE Int[CARDINAL{3}]; (* IRQ 3 выключено *)
IMPORT IOTRANSFER;
EXPORT IntHandler;
PROCEDURE IntHandler;
BEGIN
...
IOTRANSFER( ..., 0BH);
(* IOTRANSFER на IRQ 3 (Прерывание 0BH) *)
END IntHandler;
END Int;
BEGIN
...
NEWPROCESS( ...,IntProc );
TRANSFER( ...,IntProc );
NewPriority(CARDINAL(BITSET(CurrentPriority())-{3}));
(* включено IRQ 3 *)
END T.
NEWPROCESS
----------
PROCEDURE NEWPROCESS ( P : PROC;
A : ADDRESS;
S : CARDINAL;
VAR P1: ADDRESS);
Создает новый процесс. Р - это лишенная параметров процедура, которая образует новый
процесс. А - это указатель на рабочую область для процесса. Рабочая область необходима для
локальных переменных и для хранения состояния процесса при его приостановке. S - это размер
в байтах этой рабочей области. NEWPROCESS возвращает ссылку на заново созданный процесс в
Р1. Заметим, что NEWPROCESS только приготавливает процесс для выполнения, он не вызывает
начало его выполнения.
TRANSFER
--------
PROCEDURE TRANSFER(VAR P1,P2 : ADDRESS);
Передает выполнение от одного процесса другому. Текущий процесс приостанавливается и
назначается Р1, и процесс Р2 возобновляется (в его текущей точке приостановки). Р2 должен
быть результатом предыдущего запроса к NEWPROCESS или TRANSFER. Процесс Р1 будет возобнов-
лен позже, когда другой процесс передает выполнение обратно ему.
Заметим, что назначение Р1 происходит после идентификации нового процесса Р2. Это зна-
чит, что действительные параметры могут быть идентичными.
Этот тип передачи называется синхронной передачей, что противоположно асинхронной пе-
редаче, которая выполняется процедурой IOTRANSFER.
IOTRANSFER
----------
PROCEDURE IOTRANSFER(VAR P1,P2: ADDRESS; I: CARDINAL);
IOTRANSFER - это управляющая прерыванием (или асинхронная) передача. Она связывает те-
кущий процесс с номером прерывания, данным в I. Затем она приостанавливает текущий процесс
и назначает его Р1 и активизирует процесс, данный Р2. Когда процессор получает прерывание,
он проверяет, связано ли это прерывание с процессом. Если это происходит, текущий процесс
приостанавливается и назначается Р2, и (приостановленный) процесс Р1 возобновляется.
Раз прерывание и результирующая IOTRANSFEER произошли вместе, то прерывание не будет
больше связано с этим процессом.
Если большее количество процессов связано с прерыванием I, они будут обработаны в сте-
ке похожим образом, т.е. последний процесс, связанный с I будет активизирован, когда прои-
зойдет первое прерывание I, второй от конца процесс будет активизирован, когда произойдет
следующее прерывание I, и т. д.
InterruptRegisters
------------------
PROCEDURE InterruptRegisters(P: ADDRESS) : ADDRESS;
InterruptRegister может быть использован для доступа к содержимому регистров, когда
происходит прерывание. Вызывать ее имеет смысл только тогда, когда имеет место IOTRANSFER к
процессу Р. Она возвращает указатель на запись (на стек) со следующим расположением:
TYPE
ExtendedRegisters = RECORD
r : Registers;
(* как определено выше *)
IP : CARDINAL;
(* указатель команды *)
CS : CARDINAL;
(* кодовый сегмент *)
RetFlags : CARDINAL;
END;
CurrentProcess
--------------
PROCEDURE CurrentProcess() : ADDRESS;
Возвращает ссылку на текущий процесс.
CurrentPriority
---------------
PROCEDURE CurrentPriority() : CARDINAL;
Возвращает (MODULE) приоритет текущего процесса.
NewPriority
-----------
PROCEDURE NewPriority(PR : CARDINAL;
Дает текущему процессу новый (MODULE) приоритет, определяемый PR, см. описание системы
приоритетов выше.
Listen
------
PROCEDURE Listen(Mask: BITSET);
Listen временно разрешает прерывания, определенные с помощью Mask (маски), что разре-
шает принимать ожидающие прерывания. Затем эта процедура восстанавливает маску прерываний в
ее первоначальное состояние.
ПРОЧИЕ ПРОЦЕДУРЫ
================
Компилятор генерирует внутренний код для всех процедур в этом разделе.
DI
--
PROCEDURE DI();
Запрещает аппаратные прерывания. Она полезна, когда имеется доступ к данным, которые
являются общими для нескольких процессов.
EI
--
PROCEDURE EI();
Разрешает аппаратные прерывания.
Ofs
---
PROCEDURE Ofs(VAR A: WORD) : CARDINAL;
Возвращает смещение адреса А. Заметим, что адреса состоят из смещения (Ofs) и адреса
сегмента; физический адрес вычисляется как seg * 16 + ofs.
Seg
---
PROCEDURE Seg(VAR A: WORD) : CARDINAL;
Возвращает адрес сегмента адреса А.
Out
---
PROCEDURE Out(P: CARDINAL; V: SHORTCARD);
Выводит значение V в аппаратный порт Р.
In
--
PROCEDURE In(P: CARDINAL) : SHORTCARD;
Возвращает значение из аппаратного порта Р.
GetFlags
--------
PROCEDURE GetFlags() : CARDINAL;
Возвращает регистр флагов процессора.
SetFlags
--------
PROCEDURE SetFlags(F: CARDINAL);
Устанавливает регистр флагов процессора в значение, определенное с помощью F. Процеду-
ры SetFlags и GetFlags особенно полезны при запрещениях и разрешениях прерываний, для сох-
ранения и восстановления предварительных значений флагов.
МОДУЛЬ Process
==============
Процедуры в этом модуле обрабатывают одновременные процессы. Т.к. JPI Мodula-2 реали-
зуется на однопроцессорном компьютере, процессы делят между собой процессорное время пос-
редством time-slicinq (разделение времени). Другие (более низкого уровня) процедуры процес-
са могут быть найдены в модуле SYSTEM.
ПЛАНИРОВЩИК ПРОЦЕССОВ
=====================
StartScheduler
--------------
PROCEDURE StartScheduler;
Запускает процедуру разделения времени. Если она уже активна, этот запрос действия не
имеет.
StopScheduler
-------------
PROCEDURE StopScheduler:
Останавливает процедуру разделения времени. Заметим, что операции SEND и WAIT функцио-
нируют до тех пор, пока процедура не остановится (см. "СИГНАЛЫ" ).
StartProcess
------------
PROCEDURE StartProcess(P: PROC; N: CARDINAL;
Pr: CARDINAL);
Cоздает новый процесс, который выражается процедурой Р. Процесс будет распределять ра-
бочую область размером N байт (N должен быть не более 1КБ). Каждый процесс имеет приоритет,
который не должен быть перепутан с приоритетом MODULE. Pr - это приоритет процесса и должен
быть больше нуля. Если Pr больше или равен приоритету текущего процесса, то заново создан-
ный процесс станет активным.
СИГНАЛЫ
=======
Процессы могут взаимодействовать двумя различными путями: или благодаря глобальным
разделяемым переменным, или благодаря сигналам. Сигналы используются для синхронизации про-
цессов. Кроме инициализации, следующие операции могут быть выполнены на сигналах: SEND,
WAIT, Notify, и Awaited. Сигнал состоит из двух категорий: счетчик и очередь.
Init
----
TYPE SIGNAL;
PROCEDURE Init (VAR s: SIGNAL );
Инициализирует сигнал s ( т.е. его счетчик установлен в 0, и очередь пуста).
SEND
----
PROCEDURE SEND (s: SIGNAL );
Запрос SEND сделает активным 1-ый процесс, ждущий s. Если никаких процессов не ожида-
ется, запрос будет поставлен в очередь.
Операция SEND работает посредством возрастания счетчика, связанным с s. Если счетчик
< = 0, то, по крайней мере, 1 процесс ждет s и 1-ый процесс в очереди будет готов к выпол-
нению. Этот процесс также начнет выполняться, если его приоритет > = приоритета текущего
процесса.
Wait
----
PROCEDURE WAIT ( s: SIGNAL);
Запрос WAIT заставляет запрашиваемый процесс ждать соответственно SEND, если сигнал s
не имеет предварительно поставленных в очередь операций SEND.
Процедура WAIT уменьшает счетчик, cвязанный с s. Если счетчик меньше 0, это значит,
что запрашиваемый процесс должен ждать соответствующий SEND в s, и другой процесс будет ак-
тивизирован. Если счетчик больше или равен 0, то запрашиваемый процесс будет продолжаться.
Notify
------
PROCEDURE Notify (s: SIGNAL);
Заставляет задачу, ждущую сигнал s, регистрироваться, когда возможно, т.е в следующий
момент времени. Если никакой процесс не ждет s, то запрос не действует. Этот запрос не вы-
зывает перерегистрацию, таким образом, он может использоваться устройством управления пре-
рыванием (см.ГЛАВУ 7), чтобы безопасно обозначить другой процесс в момент, когда происходит
событие.
Awaited
-------
PROCEDURE Awaited (s: SIGNAL): BOOLEAN;
Возвращает TRUE (истина), если любой процесс ждет сигнал s (т.е., если счетчик, свя-
занный с s, отрицателен).
ПРОЧИЕ ПРОЦЕДУРЫ
================
Delay
-----
PROCEDURE Delay (t : CARDINAL);
Задерживает текущий процесс по меньшей мере на t интервалов времени. Интервал времени
приблизительно 1/18 с. Если t=0, перерегистрация имеет место без задержки, разрешая другому
процессу с таким же или большим приоритетом стать активным.
Lock
----
PROCEDURE Lock;
Lock предотвращает текущий процесс от перерегистрации с помощью интервала времени до
тех пор, пока не будет запрошен Unlock. Это полезно, когда процесс использует данные, кото-
рые разделяются между несколькими процессами. Запросы их к Lock могут быть вложены, но
должны быть всегда спарены с запросами UnLock.
Unlock
------
PROCEDURE Unlock;
Unlock разрешает перерегистрацию в интервал времени, и должен быть всегда спарен с
запросом Lock. Текущий процесс будет перерегистрирован, если в готовности находится процесс
такого же или большего приоритета.
Пример:
Процесс работы с клавиатурой:
MODULE KBP;
IMPORT Process,IO;
VAR
(*$W+*)
KBbuff : ARRAY[0..1023] OF CHAR;
(* циклический буфер *)
KBhead : CARDINAL;
KBtail : CARDINAL;
KeyReady: Process.SIGNAL;
(*$W=*)
PROCEDURE KBProcess;
VAR
k : CHAR;
p : CARDINAL;
BEGIN
LOOP
Process.Lock; (* Общие и ДОС-переменные использованы *)
IF IO.KeyPressed() THEN
k := IO.RdCharDirect();
p := (KBhead+1)MOD SIZE(KBbuff);
IF p <> KBtail THEN
KBbuff[KBhead] := k; KBhead := p;
END;
Process.Unlock;
IF Process.Awaited(KeyReady) THEN
Process.SEND(KeyReady)
END;
ELSE
Process.Unlock;
END;
END;
END KBProcess;
PROCEDURE GetKey() : CHAR;
VAR k : CHAR;
BEGIN
LOOP
Process.Lock; (* Глобальные общие переменные
использованы *)
IF KBtail<>KBhead THEN
k := KBbuff[KBtail];
KBtail := (KBtail+1)MOD SIZE(KBbuff);
Process.Unlock;
RETURN k;
END;
Process.Unlock;
Process.WAIT(KeyReady);
END;
END GetKey;
PROCEDURE InitKBProcess;
BEGIN
KBhead := 0;
KBtail := 0;
Process.Init(KeyReady);
Process.StartProcess(KBProcess,1000,1);
Process.StartScheduler;
END InitKBProcess;
VAR c : CHAR;
BEGIN
InitKBProcess;
LOOP
c :=GetKey();
Process.Lock; (* поскольку процедура IO.WrChar
вызывает ДОС *)
IO.WrChar(c);
Process.Unlock;
IF c=CHR(27) THEN EXIT END;
END;
END KBP.
МОДУЛЬ MATHLIB
==============
Процедуры из этого модуля выполняют общие математические вычисления. Кроме того, мо-
дуль содержит некоторые процедуры, специфичные для микропроцессора Intel 8087.
ОБРАБОТКА ОШИБОК
================
В случае ошибочных аргументов некоторые процедуры вызывают функции обработки ошибок,
определенные ниже:
MODULE MATHLIB
VAR
MathError : PROCEDURE (LONGREAL, ARRAY OF CHAR);
MathError2 : PROCEDURE (LONGREAL, LONGREAL,
ARRAY OF CHAR);
Отмечаем, что процедуры обработки ошибок являются переменными типа "Процедура", кото-
рые могут быть заменены процедурами, определенными пользователем. По умолчанию они присвое-
ны процедурам MathError и MathError2 в модуле Lib.
Процедуры обработки ошибок вызываются:
MathError Sin, Cos, Tan, Asin, Acos, Log,
Log10, Sqrt.
MathError2 ATan2.
Тригонометрические функции
--------------------------
PROCEDURE Sin(A : LONGREAL) : LONGREAL;
PROCEDURE Cos(A : LONGREAL) : LONGREAL;
PROCEDURE Tan(A : LONGREAL) : LONGREAL;
PROCEDURE ASin(A : LONGREAL) : LONGREAL;
PROCEDURE ACos(A : LONGREAL) : LONGREAL;
PROCEDURE ATan(A : LONGREAL) : LONGREAL;
PROCEDURE ATan2(X,Y : LONGREAL) : LONGREAL;
Sin, Cos и Tan осуществляют соответствующие математические функции. Аргумент А этих
процедур определен в радианах. Sin и Cos возвращают значения в диапазоне от -1 до 1.
ASin, ACos и ATan возвращают арксинус, арккосинус и арктангенс соответственно. Аргу-
мент А у ASin и ACos должен быть в диапазоне от -1 до 1. ASin возвращает значения в диапа-
зоне от -pi/2 до pi/2. ACos возвращает значения в диапазоне от 0 до pi. ATan возвращает
значения в диапазоне от -pi/2 до pi/2.
ATan2 возвращает арктангенс от X/Y. Результат - в диапазоне от -pi до pi.
Гиперболические функции
-----------------------
PROCEDURE SinH(A : LONGREAL) : LONGREAL;
PROCEDURE CosH(A : LONGREAL) : LONGREAL;
PROCEDURE TanH(A : LONGREAL) : LONGREAL;
Эти процедуры возвращают гиперболический синус, гиперболический косинус и гиперболи-
ческий тангенс соответственно переданного аргумента А.
Натуральный логарифм
--------------------
PROCEDURE Log(A: LONGREAL) : LONGREAL;
Возвращает натуральный логарифм (по основанию е) аргумента А.
Десятичный логарифм
-------------------
PROCEDURE Log10(A : LONGREAL) : LONGREAL;
Возвращает логарифм (по основанию 10) аргумента А.
Степень числа
-------------
PROCEDURE Pow(X,Y : LONGREAL) : LONGREAL;
Возвращает X, возведенный в степень Y.
Экспонента
----------
PROCEDURE Exp(A : LONGREAL) : LONGREAL;
Возвращает результат возведения е в степень А (эта
функция обратна Log).
Модуль
------
PROCEDURE Mod(X,Y : LONGREAL) : LONGREAL;
Возвращает X, являющийся абсолютной величиной Y.
Rexp
----
PROCEDURE Rexp(VAR I: INTEGER; A: LONGREAL) : LONGREAL;
Разбивает значение А на его экспоненту и мантиссу с помещением экспоненты в I, а ман-
тисса - значение, возвращаемое функцией.
Квадратный корень
-----------------
PROCEDURE Sqrt(A: LONGREAL) : LONGREAL;
Возвращает квадратный корень аргумента А.
ПРОЦЕДУРЫ ПРЕОБРАЗОВАНИЯ
========================
Две процедуры, приведенные ниже, преобразуют целую часть вещественного значения в дво-
ично-десятичное число и наоборот. Двоично-десятичное число представлено типом PackedBcd:
TYPE PackedBcd = ARRAY [0..9] OF SHORTCARD;
Две десятичные цифры упакованы в каждый элемент массива. Элемент номер 9 является зна-
ком.
LongToBcd
---------
PROCEDURE LongToBcd(A: LONGREAL) : PackedBcd;
Возвращает значение А в виде PackedBcd. А округляется к ближайшему целому. Например,
a := LongToBcd(-12345.67);
После этого вызова будем иметь значение:
элемент: 9 8 7 6 5 4 3 2 1 0
шестнадцатеричное
значение: 80 0 0 0 0 0 0 1 23 46
BcdToLong
---------
PROCEDURE BcdToLong(A: PackedBcd) : LONGREAL;
Возвращает LONGREAL представленные значения PackedBcd, заданного посредством А.
ПРОЦЕДУРЫ СОПРОЦЕССОРА 8087
===========================
За описанием управляющего слова и среды микропроцессора 8087 обратитесь к вашей доку-
ментации по 8087.
LoadControlWord
---------------
PROCEDURE LoadControlWord(C: BITSET);
Загружает сопроцессор 8087 с управляющим словом, заданным посредством С.
StoreControlWord
----------------
PROCEDURE StoreControlWord() : BITSET;
Возвращает управляющее слово микропроцессора 8087.
ClearExceptions
---------------
PROCEDURE ClearExceptions();
Стирает флаги исключения, флаг запроса прерывания и флаг занятости в слове состояния
микропроцессора 8087.
StoreEnvironment
----------------
TYPE
Environment = RECORD
ControlWord : BITSET;
StatusWord : BITSET;
TagWord : BITSET;
IP : CARDINAL;
Opcode : CARDINAL;
DataPointer : CARDINAL;
R80287 : CARDINAL;
END;
PROCEDURE StoreEnvironment() : Environment;
Возвращает среду процессора 8087, описанную посредством типа Environment. Смотри также
документацию по сопроцессору 8087.
МОДУЛЬ FIO
==========
Процедуры этого модуля используются для обработки файлов и файлового ввода/вывода. FIO
также содержит процедуры для обработки директорий.
Файлу ставится в соответствие файловая позиция, которая изменяется при операциях запи-
си и чтения. Первая позиция в файле - 0.
Файлы являются последовательными, но прямой доступ к конкретным элементам в файле мо-
жет быть достигнут посредством процедуры Seek.
Перед тем, как файл может быть прочитан или записан, он должен быть открыт использова-
нием одной из процедур Open, Create или Append. Эти процедуры все возвращают управляющую
переменную файла, которая используется во всех последующих обращениях к этому файлу. Откры-
тые файлы должны быть закрыты процедурой Close перед окончанием работы программы или когда
они не будут более использоваться.
ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ В FIO
===========================
Эти переменные используются для управления поведением и проверки результатов процедур
обработки файла и процедур ввода/вывода.
CONST
MaxOpenFiles = 15;
DiskFull = 0F0H; (* Ошибка, если при записи файлов
диск переполнен. *)
StandardInput = 0; (* MS-DOS-стандартные номера
файлов. *)
StandardOutput = 1;
ErrorOutput = 2;
AuxDevice = 3;
PrinterDevice = 4;
TYPE
File = CARDINAL; (* Тип файлового номера. *)
VAR
EOF : BOOLEAN;
IOcheck : BOOLEAN; (* Если TRUE - ошибочное
завершение программы с сообщением. *)
Separators : Str.CHARSET;
OK : BOOLEAN;
ChopOff : BOOLEAN;
Eng : BOOLEAN; (* Инженерное представление. *)
Предопределенные MS-DOS-овские стандартные номера файлов именуются от 0 до 4 как это
определено выше посредством констант. Пользовательские файлы нумеруются от 5 до значения
MaxOpenFiles. Файлы, отмеченные стандартными номерами, определены, когда программа начинает
выполнение, и не требуют открытия перед использованием.
Булевская переменная ОК устанавливается всеми процедурами форматированного ввода/выво-
да: WrBin и RdBin. Она указывает, была ли успешной предпринятая операция.
Если сделана попытка записи форматированных данных в меньшую область, чем специфициро-
вано, то записывается последовательность '?', если ChopOff - TRUE; в противном случае опи-
санный размер поля превышается. ChopOff по умолчанию - FALSE.
EOF устанавливается, если конец файла был достигнут во время последней операции чте-
ния.
Separators - множество разделителей данных, использующихся в процедуре RdItem. Значе-
ние по умолчанию:
CHARSET{CHR(9), CHR(13), CHR(26), ' '}.
Eng устанавливается, если вещественные числа сформатированы в инженерном представлении
(см. RealToStr). По умолчанию Eng - FALSE.
Если IOcheck - TRUE, то ошибки, которые случатся во время выполнения процедур, пере-
численных ниже, будут завершать программу с выдачей сообщения об ошибке. Если IOcheck -
FALSE, ошибки вместо этого могут быть проверены посредством вызова процедуры IOresult.
IOcheck по умолчанию TRUE. Следующие процедуры вызовут сообщения об ошибках, если IOcheck -
TRUE: Open, Append, Create, Close, Truncate, GetPos, Seek, Size, Erase, Rename,
ReadFirstEntry, ReadNextEntry, ChDir, MkDir, RmDir, GetDir.
ОБРАБОТКА ФАЙЛОВ
================
Файлы являются по умолчанию небуферизованными, т.е. ДОС доступна для выполнения в лю-
бое время операция чтения или записи. Для достижения большей эффективности ввода/вывода с
файлом нужно связать буфер при помощи процедуры AssignBuffer с тем, чтобы пропускать к ДОС-
у большие порции данных.
Open
----
PROCEDURE Open(Name: ARRAY OF CHAR) : File;
Открывает файл Name для чтения или записи и возвращает основу множества операций над
файлом. Позиция файла устанавливается на начало файла. Если IOcheck - FALSE и специфициро-
ванный файл не может быть открыт, возвращается значение MAX(CARDINAL).
Append
------
PROCEDURE Append(Name: ARRAY OF CHAR) : File;
Открывает файл Name, устанавливает позицию файла на конец файла, и возвращает номер
открытого файла (или MAX(CARDINAL), если файл не был успешно открыт). Выполнение операций
записи в непустой файл, открытый посредством Append, будет добавлять данные в файл вместо
того, чтобы перезаписывать их.
Create
------
PROCEDURE Create(Name: ARRAY OF CHAR) : File;
Создает файл, специфицированный посредством Name, и возвращает номер этого файла (или
MAX(CARDINAL), если файл не был успешно создан). Если файл уже существует, то предшествую-
щее содержимое его теряется. Созданный файл открывается для операций чтения или записи.
Close
-----
PROCEDURE Close(F: File);
Стирает буфер, соответствующий файлу F (если он существует) и затем закрывает файл.
AssignBuffer
------------
PROCEDURE AssignBuffer(F : File; VAR Buf: ARRAY OF BYTE);
Назначает буфер Buf файлу F. Для большой эффективности используемый размер буфера бу-
дет: N*512+BufferOverHead, где N не меньше 2.
Exists
------
PROCEDURE Exists(Name: ARRAY OF CHAR) : BOOLEAN;
Возвращает TRUE, если специфицированный файл существует. Exists использует процедуру
ReadFirstEntry для определения результата.
Erase
-----
PROCEDURE Erase(Name: ARRAY OF CHAR);
Удаляет файл, заданный посредством Name.
Rename
------
PROCEDURE Rename(Name,NewName : ARRAY OF CHAR);
Переименовывает файл Name на NewName.
Truncate
--------
PROCEDURE Truncate(F: File);
Отсекает файл F по его текущую файловую позицию.
GetPos
------
PROCEDURE GetPos(F: File) : LONGCARD;
Возвращает текущую файловую позицию файла F.
Seek
----
PROCEDURE Seek(F : File; Pos: LONGCARD);
Устанавливает файловую позицию файла F и помещает значение в Pos.
Size
----
PROCEDURE Size(F: File) : LONGCARD;
Возвращает размер файла F в байтах.
IOresult
--------
PROCEDURE IOresult() : CARDINAL;
IOresult может быть вызвана после большинства операций для тестирования успешности
операции. Нуль означает, что операция успешна, в противном случае IOresult возвращает код
ошибки, определенный в ДОС. Заметьте, что глобальная переменная IOcheck должна быть FALSE
для использования этой функции.
ФОРМАТИРОВАННЫЙ ВЫВОД
=====================
Процедуры, описанные ниже, выполняют форматированный вывод в файл. Процедура записи
возможна для каждого простого типа JPI Modula-2. Все Wr'простой-тип' процедуры ( исключая
WrChar) вызывают WrStrAdj.
Wr'простой-тип'
---------------
PROCEDURE WrChar(F : File; V : CHAR);
PROCEDURE WrBool(F : File; V : BOOLEAN; Length:INTEGER);
PROCEDURE WrShtInt(F:File; V:SHORTINT; Length:INTEGER);
PROCEDURE WrInt(F : File; V : INTEGER; Length:INTEGER);
PROCEDURE WrLngInt(F:File; V:LONGINT; Length:INTEGER);
PROCEDURE WrShtCard(F:File; V:SHORTCARD;
Length:INTEGER);
PROCEDURE WrCard(F:File; V:CARDINAL; Length:INTEGER);
PROCEDURE WrLngCard(F:File; V:LONGCARD; Length:INTEGER);
PROCEDURE WrShtHex(F:File; V:SHORTCARD; Length:INTEGER);
PROCEDURE WrHex(F:File; V:CARDINAL; Length:INTEGER);
PROCEDURE WrLngHex(F:File; V:LONGCARD; Length:INTEGER);
PROCEDURE WrReal(F:File; V:REAL; Precision:CARDINAL;
Length:INTEGER);
PROCEDURE WrLngReal(F:File; V:LONGREAL;
Precision:CARDINAL; Length:INTEGER);
Процедуры Wr'простой-тип' принимают следующие параметры: номер файла F, значение для
записи V и размер поля форматированных данных Length (не применяется для WrChar). Если
Length отрицательно, форматированные данные будут выровнены по левому краю, в противном
случае - по правому краю.
Все процедуры (исключая WrChar и WrBool) вызывают соответствующую процедуру преобразо-
вания из модуля Str для получения строкового представления значения V (см. описание модуля
Str); эта строка далее выводится с использованием WrStrAdj.
Значение типа CARDINAL может быть записано в шестнадцатеричном формате посредством
процедур WrShtHex, WrHex и WrLngHex.
WrReal и WrLngReal принимают дополнительный параметр Precision, который имеет то же
значение, что и в процедуре RealToStr (см. описание модуля Str). Глобальная переменная Eng
указывает, сформатировано ли вещественное значение в инженерной нотации.
WrStr
-----
PROCEDURE WrStr(F:File; V: ARRAY OF CHAR);
Записывает строку V в файл F.
WrStrAdj
--------
PROCEDURE WrStrAdj(F:File; S:ARRAY OF CHAR;
Length: INTEGER);
Записывает строку S в файл F, используя ABS(Length) как длину поля. Если ABS(Length)
меньше, чем Str.Length(S) и глобальная переменная ChopOff - TRUE, то последовательность
'?' записывается вместо S. Если Length отрицательна, то форматированные данные будут выров-
нены по левому краю, в противном случае - по правому краю.
Пример:
WrStrAdj(StandardOutput,'Hello',10);
WrLn(StandardOutput);
WrStrAdj(StandardOutput,'Hello',-10);
дает следующий вывод:
Hello
Hello
WrCharRep
---------
PROCEDURE WrCharRep(F:File; V:CHAR; Count:CARDINAL);
Записывает символ V в файл F Count число раз.
WrLn
----
PROCEDURE WrLn(F:File);
Записывает новую строку (CHR(13) (возврат каретки), CHR (10) (перевод строки)) в файл
F.
WrBin
-----
PROCEDURE WrBin(F:File; Buf:ARRAY OF BYTE;
Count:CARDINAL);
Записывает блок "необработанных" неформатированных данных, заданных посредством Buf в
файл F. Count - размер блока в байтах.
ФОРМАТИРОВАННЫЙ ВВОД
====================
Глобальная переменная EOF устанавливается в TRUE, если читается символ "конец-файла"
(CHR(26)) или нет более входной информации, которую можно было бы прочитать из заданного
файла.
Rd'простой-тип'
---------------
PROCEDURE RdChar (F : File) : CHAR;
PROCEDURE RdBool (F : File) : BOOLEAN;
PROCEDURE RdShtInt (F : File) : SHORTINT;
PROCEDURE RdInt (F : File) : INTEGER;
PROCEDURE RdLngInt (F : File) : LONGINT;
PROCEDURE RdShtCard (F : File) : SHORTCARD;
PROCEDURE RdCard (F : File) : CARDINAL;
PROCEDURE RdLngCard (F : File) : LONGCARD;
PROCEDURE RdShtHex (F : File) : SHORTCARD;
PROCEDURE RdHex (F : File) : CARDINAL;
PROCEDURE RdLngHex (F : File) : LONGCARD;
PROCEDURE RdReal (F : File) : REAL;
PROCEDURE RdLngReal (F : File) : LONGREAL;
Все процедуры Rd'простой-тип' получают файловую управляющую F, специфицирующую файл,
из которого будет производиться чтение, и возвращают значения 'простого типа', как указано
в приведенном выше описании.
Все процедуры (исключая RdChar) вызывают RdItem для получения последовательности сим-
волов, которая ограничена символом из глобальной переменной типа множество Separators. Эта
строка преобразуется к значению, используя одну из процедур преобразования из модуля Str.
Процедуры RdShtHex, RdHex и RdLngHex читают значения типа CARDINAL в шестнадцатеричном
формате.
Процедура RdBool возвращает TRUE, если читает строку 'TRUE', для всех других выходных
данных она возвращает FALSE.
Синтаксис для имеющих силу значений типа REAL можно найти в ГЛАВЕ 6.
Глобальная переменная ОК устанавливается в FALSE, если значение требуемого типа не мо-
жет быть прочитано, т.е., если значение имеет недопустимый формат или значение.
RdStr
-----
PROCEDURE RdStr(F:File; VAR V:ARRAY OF CHAR);
Читает строку из файла F и возвращает ее в V. Символы читаются до тех пор, пока не вы-
полнится одно из следующих условий:
- прочитан символ "конец файла" (CHR(26)), EOF установлен в TRUE, и V завершается ну-
лем;
- прочитан символ "возврат каретки" (CHR(13)). V завершается нулем;
- строка заполнена, т.к. HIGH(V)+1 символов прочитано. V завершается не нулем.
RdItem
------
PROCEDURE RdItem(F:File; VAR V: ARRAY OF CHAR);
RdItem читает строку (из файла F), которая отделена посредством символов из глобальной
переменной Separators. Строка возвращается в V.
RdBin
-----
PROCEDURE RdBin(F : File;
VAR Buf : ARRAY OF BYTE;
Count : CARDINAL) : CARDINAL;
Читает блок размером Count "необработанных" байтов из файла F и возвращает его в Buf.
ОБРАБОТКА КАТАЛОГОВ
===================
ChDir
-----
PROCEDURE ChDir(Name : ARRAY OF CHAR);
Изменяет текущую директорию. Name специфицирует новый путь для директории и может
включать имя устройства.
MkDir
-----
PROCEDURE MkDir(Name : ARRAY OF CHAR);
Создает новую поддиректорию на пути, определенном посредством Name.
RmDir
-----
PROCEDURE RmDir(Name : ARRAY OF CHAR);
Директория, специфицированная через Namе (которая должна быть пустой), исключается из
структуры директорий. Заметим, что текущая директория не может быть исключена.
GetDir
------
PROCEDURE GetDir( Drive : SHORTCARD;
VAR Name : ARRAY OF CHAR);
GetDir возвращает полное имя пути в Name для текущей директории на устройстве, специ-
фицированная через Drive (0=по умолчанию, 1=устройство А и т.д.).
ReadFirstEntry
--------------
TYPE
PathTail = ARRAY[0..12] OF CHAR;
FileAttr = SET OF (readonly,hidden,system,
volume,directory,archive);
DirEntry = RECORD
rsvd : ARRAY[0..20] OF SHORTCARD;
(* зарезервировано *)
attr : FileAttr;
time : CARDINAL;
date : CARDINAL;
size : LONGCARD;
name : PathTail;
END;
PROCEDURE ReadFirstEntry( DirName : ARRAY OF CHAR;
Attr : FileAttr;
VAR D : DirEntry) : BOOLEAN;
Ищет директорию DirName, содержащую имя устройства, путь и имя файла для файла, кото-
рый должен быть найден. Имя файла может содержать символы шаблона '*' и '?'. Параметр Attr
требует некоторого объяснения: если он - пустое множество, то ищется только вхождение нор-
мальных файлов (то же применяется, если установлены атрибуты readonly и archive); если
должно быть взято в расчет вхождение скрытых файлов, системных файлов или директорий, то
соответствующий атрибут должен быть установлен; наконец, если установлен атрибут volume, то
возвращается только имя тома.
Если подходящее вхождение найдено, ReadFirstEntry возвращает TRUE, и D будет содержать
директорию вхождения.
Смотри также процедуру ReadNextEntry.
Пример:
ReadFirstEntry("c:\com\*.*",FileAttr{hidden,system,
directory},e)
Подходящими будут все файлы директории "c:\com", и e будет содержать первое вхождение
(если результат функции - TRUE).
|