\section{Реализация CLI}{Реализация командных интерфейсов}

Командные языки обычно имеют более простой синтаксис, чем языки
программирования, что упрощает интерпретатор. Однако большинство
таких языков функционально полны, то есть пригодны для реализации
любых алгоритмов. Эти языки предоставляют переменные с возможностью
разрушающего присваивания, условные операторы, циклы и операторы
перехода. Переменные обычно представляют собой текстовые строки,
над которыми определены операции слияния строк, сравнения на равенство
и на больше/меньше, выделения подстрок и, нередко, арифметических
операций, когда строки интерпретируются как десятичные числа.

Командные интерпретаторы в современных ОС способны принимать команды как
с клавиатуры системной консоли или терминала, так и из файла. Прием команд
из файла обеспечивает возможность создания \term{командных файлов}
или \termin{скриптов}{scripts}. Единственное, что требуется со стороны
ОС для поддежки этой возможности -- это предоставление однородных
средств для обмена данными с терминалом и файлом. Все современные ОС
предоставляют такие средства.

Наиболее сложным механизмом в командных языках является механизм передачи
параметров вызванной программе. Такой механизм обязан пользоваться поддержкой
со стороны ОС, потому что он требует передачи данных между родительской
задачей (оболочкой) и порожденной. Этот механизм используется очень часто --
при каждом вызове программы -- поэтому кажется целесообразным создать
специализированный механизм, а не пользоваться универсальными средствами
типа разделяемой памяти и т.д.

{\small
В системах семейства \sysname{Unix} и ряде других систем (\sysname{DOS},
\sysname{OS/2}, \sysname{Windows NT}) параметры передаются программе
как упорядоченный набор текстовых строк.
В \sysname{UNIX} системные вызовы семейства \verb"exec" принимают
эти параметры как таблицу указателей на строки.
Например, один из вызовов этого семейства имеет формат:
\verb|int execv(const char * program, const char ** argv);|
В данном случае таблица завершается нулевым указателем.
Такой механизм позволяет передать произвольное количество отдельных
параметров, хотя полнный объем передаваемых таким образом данных ограничен.
В \sysname{UNIX SVR4} в виде позиционных аргументов может быть передано
не более 4К байт.
Переданные параметры копируются в стек создаваемой задачи;
в стеке же создается таблица указателей на эти строки. Указатель на
начало таблицы и ее длина передаются точке входа программы
(функции \verb|main()| в языках \progname{C/C++}) как параметры.

Имя загрузочного файла программы передается в качестве первого
позиционного аргумента. Некоторые системные программы используют
собственное имя как один из параметров. Например, экранный редактор
\verb|vi|, программа просмотра файлов \verb|view| и строчный редактор
\verb|ex|, в действительности, представляют собой различные имена
одного и того же загрузочного модуля. Этот модуль анализирует первый
аргумент и включает соответствующий режим в зависимости от его значения.

Кроме позиционных аргументов программа получает также список переменных
оболочки -- \termin{среду}{environment}. Этот список также передается
в виде массива строк. Каждая строка имеет формат \verb|"ИМЯ=значение"|.
Указатель на начало массива также передается точке входа программы
в качестве параметра.

В \sysname{DOS} и \sysname{OS/2} командные процессоры передают позиционные
параметры <<как есть>>: так, как они были набраны в строке, без какого либо
преобразования и/или контроля. Командные процессоры ОС семейства
\sysname{Unix} выполняют только одно преобразование, известое как
\termin{раскрытие шаблонов}{wildcard expansion}.
Если элемент командной строки содержит символы \verb|'*'|, \verb|'?'| и
\verb|'['|, командный процессор рассматривает такой параметр как шаблон
имени файла и заменяет его на имена всех файлов, соответствующие шаблону%
\footnote{Синтаксис шаблона подробно описан в ряде справочных и учебных
руководств, например, в \cite{RedPOSIX}.}. Таким образом, если текущая
директория содержит файлы:
\begin{example}
\small
\begin{verbatim}
protocol.h  client.c    server.c      utils.c
client.o    server.o    utils.o       a.out
server      client      core          Makefile
backup.zip
\end{verbatim}
\end{example}
командная строка будет \verb|zip backup.zip *.c *.h| будет
передана команде в виде аргументов: \verb|"zip"|, \verb|"backup.zip"|,
\verb|"protocol.h"|, \verb|"client.c"|, \verb|"server.c"|, \verb|"utils.c"|.
Таким образом, программе не нужно заниматься распознанием
аргументов-шаблонов и их раскрытием; ей достаточно уметь принять
много аргументов-имен файлов. Такой подход упрощает разработку программ,
точнее -- написание модулей, занимающихся разбором аргументов, но усложняет
вызов программ, использующих шаблоны для объектов, не являющихся файлами:
параметр-шаблон просто не доходит до программы.

Например, командная строка \verb|unzip backup.zip *.h|
будет преобразована в аргументы: \verb|"unzip"|, \verb|"backup.zip"|,
\verb|"protocol.h"|. Скорее всего, это не то, чего мы хотели -- ведь
архив \verb|backup.zip| может содержать и другие файлы с именами,
оканчивающимися на \verb|.h|. В данной ситуации проблему можно решить,
написав \verb|unzip backup.zip "*.h"|\footnote{Двойные кавычки запрещают
раскрытие шаблонов}, но можно привести более сложный пример: известная всем
пользователям \sysname{DOS}, \sysname{OS/2}, \sysname{Windows NT}
и систем фирмы \entname{DEC} конструкция \verb|COPY *.C *.BAK|.
Эта команда должна скопировать все файлы с расширением \verb|.C|
в одноименные файлы с расширением \verb|.BAK|.

Легко понять, что реализовать такую команду в командном процессоре
\sysname{UNIX} простым способом невозможно. По-видимому, одним из самых
простых способов выполнить такое действие будет следующая программа%
\footnote{Знатокам \sysname{UNIX} в качестве упражнения предлагаются
два вопроса:
\par Для чего первая точка в аргументе команды \verb|sed|
заключена в скобки?
\par Для чего нужен символ {\tt <<\$>>} в аргументе команды \verb|sed|?}:

\begin{example}
\small
\begin{verbatim}
#!/bin/sh

for i in *.c; do
  cp $i `echo $i | sed -e 's/[.]c$/.bak/'`
done
\end{verbatim}
\end{example}

В свете этого решение разработчиков фирмы \entname{Microsoft}
возложить раскрытие шаблонов на прикладные программы представляется,
во всяком случае, обоснованным.

Несколько дальше пошли в обработке параметров разработчики командного
процессора \progname{DCL} -- DEC Command Language, командного языка,
использующегося в \sysname{RT-11}, \sysname{RSX-11} и \sysname{VMS}.
В этом языке программы запускаются командой \verb|RUN| и не принимают
параметров. Если же пользователь хочет зарегистрировать команду,
он должен создать файл описания команды на специальном языке.
В файле описания содержатся описатели всех параметров и ключей команды
с указанием того, является ли данный параметр/ключ обязательным,
а если не является, то какое значение следует взять по умолчанию.
В зависимости от значений параметров и ключей можно потребовать
запуска различных программ. Затем новая команда регистрируется командой
\verb|SET COMMAND ИМЯ_ФАЙЛА_ОПИСАНИЯ|. Запущенные программы могут получить
значения параметров и ключей, исполнив соответствующие системные вызовы.


\section{Реализация GUI}{Реализация графических интерфейсов пользователя}

Графические интерфейсы предъявляют довольно высокие требования
к ресурсам системы, в первую очередь -- к оперативной памяти,
центральному процессору и скорости обмена данными с графическим
устройством. Единственным известным на сегодня способом реализации
графического интерфейса является очередь событий, генерируемых
при нажатиях клавиш и движении позиционного указателя (мыши и т.д.).
Современные ОС обычно предоставляют очереди событий в виде отдельного
средства межпроцессного взаимодействия или даже реализуют их через
другие средства, как, например, \progname{X11 Window} передает события
через сетевые сокеты.

При реализации графических оболочек визуальному дизайну часто уделяется
гораздо больше внимания, чем технологической стороне дела. Это во многом
оправдано, так как техническая сторона этих оболочек обычно достаточно
проста.

% Смысл примерно такой: пользователи GUI ценят в них простоту использования
% и {\em однородность} интерфейса. То есть все GUI-программы в данной
% среде должны вести себя примерно одинаково.
% В этом отношении представлятся не совсем правильным подход X Windows,
% что <<X определяет протокол, но не политику>>
% Попытки стандартизовать GUI:
% CUA 91 (Common user access): OS/2 1.x, отчасти Windows 3.x, Windows 95.
% Объектно-ориентированный CUA 93: OS/2 2.x/3.x
% Motif.

% Вообще-то я планировал в этом разделе еще длинное рассуждение про
% componentware vs. заранее интегрированных аппликух, но это лучше
% отложить до лучших времен :).
