Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |
5.4.4 Для операторов передачи управления Go, Do и If решено, что оператор Do передаёт управление "точно" — в точности той строке, которая ему указана. Её отсутствие вызывает ошибку. А вот операторы Go и If передают управление "примерно": указанной строке, или следующей после неё, если она отсутствует.
5.4.5 Решено, что в операторе Ret тоже может быть выражение. Если данную подпрограмму вызвали с помощью спецфункции FSUBr — его значение она и вернет. А если нет — оно просто попадёт в аккумулятор для чисел. В точности как значение выражения в операторе X.
5.4.6 О! В операторе X за каким-то контрабасом разрешили не одно выражение, а несколько — через запятую. (И в операторе Set тоже, видимо за компанию.) В числовом аккумуляторе остаётся значение последнего.
* * *
Уж коли речь зашла об аккумуляторах, то может пора вспомнить что их у нас вдруг оказалось три. И остальные два напрямую связаны с вводом/выводом.
1.0.1 Вспомним, что у Фокала есть один канал ввода, откуда берёт данные оператор Ask, функция FCHR и "интерфейсная" часть интерпретатора, когда она хочет очередную командную строку; и один канал вывода, куда пишут операторы Type и Write, функция FCHR а "интерфейсная" часть выдаёт звёздочку — традиционное приглашение Фокала ко вводу очередной командной строки. И еще оператор Ask выдаёт туда двоеточие — своё приглашение ко вводу. Или текстовые константы, буде они в нём есть — с той же самой целью.
Решено, что оная звёздочка (равно как и двоеточие оператора Ask), предназначается только и исключительно пользователю, сидящему за терминалом. За сим и выдаваться они будут только и исключительно на терминал, вне зависимости от того, куда указывает канал вывода. Но только в том случае, если ввод — с клавиатуры. И текстовые константы оператора Ask тоже. Причем наличие текстовой константы, даже пустой, подавляет вывод двоеточия.
1.0.2 Вспомним, что вышеупомянутые каналы переключал оператор Operate. ("Оперировать", "манипулировать"...) Причем набор устройств ввода/вывода был фиксированный. Поэтому они обозначались вторым ключевым словом. И путаницы, что подключить к каналу ввода а что — вывода, не возникало. (Клавиатура и перфосчитыватель — только на ввод; терминал, перфоратор и принтер — только на вывод.)
А вот теперь в нашем распоряжении файловая система. И файлов в ней столько!.. Но чтобы файлом воспользоваться, его сперва надо "открыть", а потом, когда надоест — "закрыть". А еще к файлу прилагается "текущая точка", оно же "указатель ввода/вывода". Если бы файл был магнитной лентой, то это была бы магнитофонная головка. Её можно передвигать. Перематывая ленту.
Вот только на настоящую магнитную ленту писать получается только в конец. Вернее конец автоматически образуется там, куда пишем. А у файла такого нет: пишем поверх того что было, а то что после этого места — не пропадает.
А еще, один и тот же файл можно открыть как для чтения так и для записи. А так же для того и другого одновременно.
И всё это пришлось поручить оператору O, дав ему в помощь функцию FTEll чтобы сообщала текущее положение указателя чтения/записи. Впрочем, у него как раз название подходящее: можно трактовать и как Open — "открыть". А что значит "tell" — понятия не имею: в Си-шной библиотеке ввода/вывода такая функция сообщает положение указателя.
1.1 Оператор Open обязательно содержит второе ключевое слово. Которое теперь "псевдоним" открытого файла. Он может быть на любую букву алфавита.
Если ничего кроме этого самого псевдонима в операторе O больше нет — он как и раньше переключает канал ввода или вывода. На файл, открытый под этим псевдонимом. А так как файл может быть одновременно открыт и на чтение и на запись, то какой канал переключать определяем по остальным символам оного псевдонима: если там среди них есть буковка "R" (намек на слово read — "чтение"), то переключаем канал ввода. А если нету — то вывода.
Если перед псевдонимом вдруг есть текстовая константа, то это имя файла, который надо открыть. Если псевдоним уже занят — открытый под ним файл сперва закрывается. А если текстовая константа пустая — то только закрывается.
Если кроме имени файла там еще выражение в скобках — то указатель чтения/записи сразу ставится в указанную им позицию. Если есть только скобочки с выражением — то только позиционируется. А если скобочки эти — пустые, то не делается ничего. Но всё равно это операция ввода/вывода (хотя и фиктивная) и в "аккумулятор" для функции FTEll этот объект таки попадает.
Кстати, сообщает что туда попало — сам же оператор Oper — если в нём псевдонима нет. Так же как и W — в форме, пригодной для обратного ввода. (А то W O как вывалит до кучи весь список чего наоткрывать успели!...)
Как именно открывать файл — тоже показывают дополнительные буковки псевдонима. Которые, в отличии от других ключевых слов, не все игнорируются. В данной версии задействованы: R W A B T N, указывающие на чтение, запись, добавление, "бинарный" режим открытия файла и соответственно "текстовый". А буква N велит не очищать (при вот данной операции) уже упоминавшийся аккумулятор под текстовую строку. (Чтобы учинять с ним разные фокусы.) А то при переключении каналов ввода/вывода он обычно автоматически очищается.
### Форма, когда имя файла ПОСЛЕ псевдонима, (через знак =) как это описано в главе 12 оной книжки (к коей вот это всё — якобы приложение), здесь не реализована.
1.2 Когда Фокал еще только-только запущен, уже задействованы: Т — терминал и К — клавиатура. А так же: Л — стандартный принтер и Ц — стандартный компорт. Ну и разумеется каналы ввода, вывода и вывода ошибок — I O E. Это их ДОС автоматически открывает.
У нас все-таки не UNIX — терминал с клавиатурой доступны не только через стандартный ввод/вывод (вот эти самые I O E), но и напрямую. Но уж коли ДОС всё это предоставил — пусть будут доступны.
## Вот только толку от них — ноль! Даже меньше: из за того, что буква Ц оказалась вдруг занята, приходится автоматически открывать не все указанные в командной строке файлы (как это было первоначально задумано), а только два первых. И это при том, что драйвер компорта в ДОС`е примитивно-примитивный — для любой реальной задачи придётся делать свой. А с перенаправлением ввода/вывода вообще засада... Так что с этим пока поосторожнее.
1.3 Ежели при запуске интерпретатора в командной строке указаны имена еще каких-то файлов (а что там еще может быть?) то первые два открываются автоматически под псевдонимами А и Б. Причем на А сразу же переключается канал ввода. На предмет программку оттедова загрузить...
А если нету — делается попытка открыть файл "sav.f" в текущем каталоге — тоже под псевдонимом А и с той же самой целью. Потому что когда пользователь пытается выйти из Фокала, нажав ESC, перед выходом ему предлагается сохранить там программу. Да и переменные тоже. (Это если он программу правил.)
* * *
Ну это чтобы следующий сеанс работы был продолжением предыдущего.
5.2.1 С той же самой целью содержимое пула (мешка) ранее введенных с помощью редактора строк при выходе автоматически выгружается в файл "_fpks.txt" а при запуске загружается обратно.
Но правда только если такой файл в текущем каталоге уже есть. Или если есть переменная среды FPKS. Где, кстати, может быть указано и какое-то другое имя: FPKS=имя_файла.
5.2.2 Экранный редактор командной строки, облегчающий пользователю её ввод, завершает редактирование по нажатию кнопок ВК (она же "ввод" или "Enter"), и ESC (она же АР2 или "эскейп"). В первом случае редактирование строки завершается "успешно" и она передаётся тому, кто её у редактора запросил. (А это может быть оператор Ask и сам интерпретатор, вернее его "интерфейсная" часть.) А по нажатии ESC — "неуспешно". (Запросившему возвращается ноль.) Но это только если строка пуста. Если нет — она только очищается.
Оператор Ask, получив от редактора ноль, просто оставляет значение переменной без изменения. (Еще и на терминал выводит.) А вот сам интерпретатор пытается завершить свою работу. (Ну пользователь же эскейп нажал — выйти наверно хочет!) Но сперва проверив — не редактировал ли пользователь программу, действенно напоминает ему что надо бы сохранить результаты его трудов! Формирует и предлагает пользователю примерно такую командную строку:
o "sav.f" sw;o s;w a;w s;t "o k"!;o "" s;q После чего считает свою миссию выполненной. (Признак этот сбрасывает.)
Разумеется, пользователь может сделать с этой предложенной ему командной строкой всё что хочет. В т.ч. заменить имя файла на своё собственное. Или стереть лишнее, или, если ему не надо ничего сохранять — стереть всю эту строку нафиг, еще раз нажав ESC. И еще раз нажав ESC таки выйти!
5.3.5 Функция FTEll задумана чтобы просто сообщать положение указателя чтения/записи для открытого файла. (Того, который поучаствовал в последней по времени операции ввода/вывода (пусть даже и фиктивной) — потому что его псевдоним только в операторе Oper и больше нигде.) Но на неё еще свалили всё, что не знали кому поручить.
— сначала — еще и сообщать длину файла (когда ф-я FTEll — с аргументом)
— далее, для терминала, не имеющего ни длины ни текущей точки (есть аналоги, но с ними имеют дело функции FKурсор и FVizual), FTEll запрягли сообщать признаки удержания в нажатом виде "интересных" кнопочек: Cntrl, Alt, Shift.
— и плюс к тому — проверять односимвольный буфер клавиатуры. В принципе туда лазит и функция FCHR. Но она код нажатой кнопки оттуда заберет, а сам буфер очистит. А если он был пуст — будет ждать до морковкиного заговенья, пока пользователь соизволит нажать какую либо кнопку. А FTEll просто проверяет.
— потом еще ей поручили искать файлы в текущем каталоге. По имени, указанному аргументом в виде текстовой константы. (С пустой — следующий.)
— и сообщать об этом, ею же самой в прошлый раз найденном файле — тоже размер, а кроме того и время создания. (Или -1, если небыл найден.)
— и в довершении всего — еще и добывать из недр интерпретатора разные всякие текстовые строки. И складывать их в третий из вышеупомянутых аккумуляторов, тот, что вот как раз для хранения текстовой строки. (В т.ч. элементы "программного окружения", это которое environ.)
Как же всё это удалось? Ой, и не спрашивайте! (В хелп загляните.)
Ну так я сам заглянул — всё просто: FTEll(,,X). Если X — число, то получаем параметр из командной строки, если строка — имя переменной из environ, то её значение. Если таковая есть. Иначе возвращает -1.
4.0.1 Этот самый якобы аккумулятор для хранения одной текстовой строки — ни что иное, как входной буфер оператора Ask.
В принципе у Фокала два таких буфера. Второй принадлежит самому интерпретатору. Он вводит туда очередную командную строку и пока всю её не выполнит — за следующей не лезет. Так что операторы, в этой, уже находящейся в памяти строке, могут творить в том числе с файлом, откуда она взята, всё что им вздумается. Благо, в строке их помещается много...
Оператор Ask тоже вводит за раз целую строку, а "потребляет" из неё только одно выражение, в то время как их в ней может быть несколько. Соответственно, буфер снабжен указателем, отделяющим уже использованную его часть от еще нет.
Функция FCHR, вводящая байты поштучно, читает их прямо из файла (или из уже упоминавшегося буфера клавиатуры) только в том случае, если буфер оператора Ask — пуст. А если нет — берет символ оттуда.
По-другому некрасиво получается.
Но и так — тоже не всё хокей... В общем нужны средства что-то с этим буфером сделать. В первую очередь — очистить. Чтобы следующее число (или выражение) было с начала следующей строки...
4.1.1 Для очистки оного буфера (он же "строчный аккумулятор) ввели конструкцию "формат" и для оператора Ask: теперь Ask % — чистит этот свой буфер, делая его пустым.
5.2.3 Хотим чтобы сидящий за терминалом пользователь совсем обленился: не вводил сам значения, которые от него хочет оператор Ask, а получал в уже почти готовом виде и мог просто согласиться, или чуть подредактировать.
Ну и кто подобное сможет организовать? Конечно же сам оператор Ask! Делает же это интерпретатор, предлагая в ответ на нажатие ESC почти готовую строку для сохранения программы. Чем оператор Ask хуже?!
Для этого надо проделать следующий фокус-покус: текст, который редактор выдаст в редактируемой строке пользователю, должен быть помещен вот в этот самый буфер, но так, чтобы он остался пустым. ВЫГЛЯДЕЛ пустым! (Что оказывается совсем не то же самое.) Надо чтобы указатель начала еще неиспользованной части указывал на конец буфера. Типа всё содержимое уже использовано. Что, впрочем, сделать не так уж просто: как только Ask или FCHr берёт из буфера последний символ, он же его сразу и очищает до состояния "нету буфера". (FCHr(,0) или FCHr(,) возвратит после этого -1.) А нам надо чтобы был. Надо либо принудительно туда этот указатель поставить, либо...
Вот для этого теперь у Ask есть спецформат %%. Он тоже очищает буфер, но главное: после него (и до конца оператора, или до !) Ask начинает работать так же как Type, но не в канал вывода, а вот в этот свой буфер. (Т.е. выражения вычисляются и результат преобразуется в текст по текущему формату оператора Type, а текстовые константы выводятся как есть.) Спецформат %%% делает то же самое, но сохраняет "уже использованную" часть. (Т.е. позволяет добавлять к тому, что туда поместил предыдущий оператор.)
/// примечание: раньше это было до ближайшей запятой — из соображений, что
одного выражения вполне достаточно (а ! просто игнорировался)
и сейчас я весь в раздумьях — как лучше и логичнее? \
4.1.2 Оператор Ask вводит строку в буфер (если он конешно пуст), но сам же её и потребляет. Чтобы только вводил, но ничего с этой строкой не делал — форма оператора Ask с абсолютно пустым списком ввода. (Весь оператор из одного только ключевого слова.)
Внимание: в операторе и в самом деле не должно быть абсолютно ничего. Одна приблудная запятая испортит всю малину. Но таки может быть формат вида %N. (Где N — числовая константа.) Что бы это ни значило.
5.2.4 Сейчас формат %N в Ask работает только для терминала — указывает редактору ширину поля ввода. Каковое простирается от того места экрана, где стоял "маркер" (он же "курсор") — указывающий текущую позицию. И до правого края экрана. Или же ровно на N символьных позиций.
Последнее — для того, чтобы на экране можно было нарисовать табличку и что-то вписывать в её графы: поставил (функцией FCS она же FKурсор) курсор в начало поля, указал его ширину и вводи, не трогая соседние поля...
Причем, такой формат полагается всем операторам ввода, в т.ч. Modify...
А табличку эту нехай сама FKурс нарисует — символами псевдографики...
* * *
Но про управление экранным курсором — попозже. Сейчас мы заполучили текстовую строку в аккумулятор, и надо срочно изыскать хоть какие-то средства, чтобы можно было хоть что-то с нею там сделать.
Аналогом экранного курсора у нас здесь вот этот самый указатель, отделяющий "уже использованную" часть буфера от "еще нет". (Так и хочется назвать его тоже "маркером".) Так, если по-минимуму, нам надо читать/писать символ, на который он указывает; двигать его куда захотим и определять — сколько есть символов до него и после.
Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |