Глава 10. Программирование в Linux
GNU cc ≈ компилятор С системы Linux
Программирование на С
Команда cc Компиляция: усложненный вариант
Работа с cc
Параметры командной строки cc
Компоновка библиотек
Разделяемые библиотеки Linux
Программирование на C++
Программирование для Х
LessTif Компиляция LessTif
Диагностика проблем в LessTif
Использование поддержки приложений Motif в Editres
Дополнительная информация о LessTif
XForms
Инструментарий программиста Make
Отладчики
Утилиты X Window
Синтаксические и лексические анализаторы
Прочие утилиты
Java
Другие языки программирования
Языки сценариев Tcl
Perl
Python
Gawk
Итоги

 
 
 
 
 
 
 
 
 
 
  Глава 10. Программирование в Linux


 
 

Конечно, чтение этой главы не научит вас программировать для Linux и Х Window. Однако мы покажем, как программировать для среды Linux, и обсудим много особенностей, которые необходимо знать программисту. В частности, вы узнаете, где находятся библиотеки Х и как в Linux используются общие библиотеки.

Linux предлагает программистам все бесплатные утилиты и компиляторы, присущие операционной системе, которая в значительной степени основана на продуктах Фонда бесплатных программ. В системе Linux можно программировать на С (начиная с компилятора GNU С, модифицированного фирмой Cygnus), C++, Fortran (с помощью g77) и Objective-C. Помимо этих распространенных языков, Linux поддерживает Tcl, Perl, Python и многие другие языки и средства программирования. Также существует LessTif ≈ бесплатный аналог Motif для тех, кто хочет обеспечить Motif-совместимость и обойтись без затрат на коммерческие программы. Многочисленные средства разработчика позволяют выбрать подходящий инструмент для любой конкретной ситуации.

Прежде всего проверьте, установили ли вы компоненты своего компилятора и сопровождающие утилиты (для тех, кто не в курсе: компилятором называется программа, которая преобразует программу в исходном тексте в исполняемый файл Linux). Впрочем, даже если необходимые компоненты не были установлены, вы всегда можете запустить программу setup и переустановить нужные пакеты.

Если вы не программист, вероятно, большая часть материалов этой главы останется для вас непонятной. Но даже в этом случае вы откроете для себя ряд интересных средств Linux. Кроме того, многие бесплатные программы Linux распространяются только в виде исходных текстов. Вам придется откомпилировать их, а для этого необходимо хорошо разбираться в компиляции и компоновке программ на языке С.

GNU cc ≈ компилятор С системы Linux Основной компилятор С и C++ в Linux основан на GNU cc. В UNIX компилятор С традиционно называется cc (сокращение от С compiler, то есть ⌠компилятор С■). В проекте GNU к названию добавилась буква g (разумеется, от GNU). Компилятор С в Slackware Linux был предоставлен фирмой Cygnus и называется egcs. Он является видоизмененной версией распространенного компилятора GNU gcc. Эта универсальная программа компилирует программы, написанные на разных языках программирования ≈ С, C++, Fortran и Objective-C.

Базовая команда остается прежней ≈ gcc (или cc). Она компилирует программы на С и C++ с использованием всех стандартных параметров cc, а также традиционных параметров gcc. Если вы привыкли программировать для UNIX, вы убедитесь, что программирование в Linux не имеет ничего принципиально нового.

Для новичков мы включили короткое вступление. Если вы совсем не разбираетесь в программировании, купите книгу по языку С. Несколько таких книг перечислено в приложении А.

Программирование на С Программы на языке С, как и большинство других программ, начинают свое существование в виде обычных текстовых файлов (как вы могли неоднократно убедиться в этой книге, обычные текстовые файлы широко используются в Linux). Эти текстовые файлы создаются в редакторах (например, vi или emacs). Готовая программа на С обрабатывается программой-компилятором С ≈ cc или gсс (в Linux это одно и то же). Компилятор преобразует текстовый файл, написанный программистом, в объектный или машинный код для платформы Intel. Объектные модули (файлы объектного кода) затем обрабатываются программой-компоновщиком, в результате чего появляется исполняемая программа. После успешного завершения этого процесса исполняемый файл можно запустить так же, как и обычную команду, ≈ достаточно ввести его имя в командной строке. Таким образом, вы получаете возможность создавать собственные команды.

Прежде всего необходимо определить, с какими файлами вы имеете дело. Большинство программ на С хранится в файлах с суффиксом .с ≈ например, neatstuff.c и myprog.c.

В результате компиляции исходных текстов компилятор С, cc, создает объектный файл. Обычно объектные файлы имеют суффикс .о. Затем компоновщик, или ⌠редактор связей■ (linkage editor) в терминологии Linux, ld, производит компоновку файлов .о для построения исполняемой программы. По умолчанию используется имя a.out, хотя в действительности никто не называет свою программу этим именем. Вместо этого программам присваивается более осмысленное имя ≈ например, ls, cp или fvwm95. Весь описанный процесс производится под управлением команды cc.

Имя a.out не имеет отношения к одноименному старому формату объектных файлов Linux, упомянутому при обсуждении файлов ELF. В табл. 10.1 перечислены некоторые распространенные типы файлов (а точнее, суффиксы), часто встречающиеся при программировании.
Таблица 10.1. Типы программных файлов
 
Файловый суффикс
Значение
Библиотека
Программа на С
Программа на C++ (обратите внимание на регистр С)
.cc Программа на C++
.class Откомпилированный класс Java
.срр Программа на C++
.схх Программа на C++
.c++ Программа на C++
.f Программа на Fortran
.for Программа на Fortran
.h Заголовочный файл С или C++
.hxx Заголовочный файл C++
.java Программа на Java
.m Программа на Objective-C
.o Объектный модуль (как правило, полученный компиляцией файла на языке С или C++)
.pl Сценарий Perl
.pm Сценарий модуля Perl
.s Ассемблерный код
.sa Заглушки общих библиотек, подключаемых к программе
.so.n Динамическая общая библиотека, n ≈ номер версии
.tcl Сценарий Tcl
.tk Сценарий Tcl/Tk

 

Команда cc

Команда cc запускает компилятор С, который компилирует и компонует программы на языке С в исполняемые файлы. Чтобы убедиться в наличии компилятора, введите следующую команду: $ gсс -v Результат должен выглядеть так: Reading specs from /usr/lib/gcc-lib/i586-pc-linux-gnulibcl/egcs-
2.90.29/specs
gcc version egcs-2.90.29 980515 (egcs-1.0.3 release)
Команда cc делает в точности то же самое; в этом нетрудно убедиться, вводя аналогичную команду: $ cc -v Если вы увидите приведенный выше результат, значит, на вашем компьютере имеется установленный компилятор С.

Следующий шаг ≈ убедиться в том, что установленных компонентов хватает для компиляции и компоновки рабочих программ.

Для проверки компилятора С в Linux мы используем короткую программу, приведенную в листинге 10.1.

Листинг 10.1. Короткая программа на языке С /*
* Example С program for Chapter 10.
* Linux Configuration and Installation.
*/
#include <stdio.h>
int main(int argc, char** argv)
{
/* This is a comment */
printf("Linux is my favorite O.S. \n");
return 0;
}
/* chap10.c */
Введите этот фрагмент (исходный текст программы) в текстовый файл chapl0.c, используя свой любимый текстовый редактор.

Файлы, содержащие программы на языке С, обычно должны иметь расширение .с. Это необязательно, однако соблюдение подобных правил упрощает работу в Linux.

Когда эта короткая программа будет введена, выполните описанные ниже несложные действия, чтобы создать исполняемую программу.

Введенная программа хранится в обычном текстовом файле. Ее необходимо преобразовать в исполняемый код. Для этого мы должны откомпилировать и скомпоновать программу. Оба действия выполняются следующей командой cc:

$ cc -о chap10 chap10.c Эта команда запускает компилятор С (cc). Параметр -о сообщает cc о том, что построенная программа должна называться chap10 (без параметра -о по умолчанию используется неуклюжее имя a.out). Последний параметр (chap10.c) указывает cc на то, что компилировать следует файл chap10.c. Команда cc выполняет компиляцию и компоновку программы.

В результате вы получаете исполняемую программу с именем chap10. Попробуйте запустить ее командой chap10 в командной строке. На экране появляется следующий текст:

$ chap10
Linux is my favorite O.S.
Поздравляем, вы приобщились к программированию на С. Начало новой блестящей карьеры положено.
Компиляция: усложненный вариант Команда cc сначала компилирует программу в объектный модуль, а затем компонует объектный модуль и создает исполняемый файл chap10. Это очень важно, если в программе компилируется несколько файлов. Большинство программ на С состоит из нескольких файлов с расширением .с, все они должны быть откомпилированы и скомпонованы в одну программу. Одна из главных причин для разделения программ на файлы ≈ здравый смысл; ни один нормальный человек не сможет прочитать исходный текст мегабайтной программы в одном исходном файле. Да, программы на С действительно достигают таких размеров. У некоторых программистов, с которыми нам приходилось работать, программы содержали до миллиона строк. Вы должны уметь компоновать несколько файлов .с в один исполняемый файл.

Чтобы использовать длинный вариант компиляции и компоновки, мы разобьем задачу на два этапа. Сначала вы компилируете все исходные файлы (.с), создавая для каждого файла объектный файл (.о). Затем полученные объектные файлы объединяются в одну исполняемую программу. У нас уже имеется очень маленькая программа на С (ведь вы ввели ее, не правда ли?), с нее и начнем.

Откомпилируйте файл chap10.c в объектный модуль следующей командой:

$ cc -с chap10c Если компиляция прошла успешно, в каталоге появится файл chap10.o. Он называется объектным файлом (или объектным модулем) и содержит некомпонованный машинный код.

Следующий шаг ≈ скомпоновать объектные файлы (обычно таких файлов несколько) в один исполняемый файл. Для этого мы снова вызываем cc с параметром -о, но на этот раз командная строка завершается объектным файлом (.о), а не файлом с исходным текстом программы:

$ cc -о chap10 chap10.o Команда производит компоновку файла chap10.o в исполняемый файл chap10. Как показывает следующий пример, в командной строке можно указать несколько объектных файлов: $ cc -о chap10 chap10_a.o chap10_b.o chap10_c.o Рекомендуем выбрать более содержательные имена, нежели те, которые были использованы в данном примере.
Работа с cc Обычно команда cc незаметно для вас выполняет несколько других команд. Одна из этих команд ≈ срр, препроцессор языка С. Она читает программный файл на языке С и расширяет директивы #. В короткой программе из предыдущего раздела присутствовала директива #include, которая включает в программу файл stdio.h. Другими словами, срр читает файл stdio.h и вставляет его содержимое вместо директивы #include. В большинстве программ на С включается один или несколько файлов, которые называются включаемыми (include files) или заголовочными файлами (header files).

Включаемые файлы обычно хранятся в каталоге /usr/include. Если имя файла в директиве заключено в угловые скобки (например, <stdio.h>), срр ищет файл stdio.h в стандартных местах, что в данном случае означает каталог /usr/include. Параметр -I позволяет добавить в путь поиска другие файлы (табл. 10.2). Имя файла также может быть заключено в кавычки.

Все программы на С содержат центральную секцию mainO. Эта секция (в терминологии С называемая функцией) выполняется при запуске программ. Наша функция main() ограничивается вызовом функции printf(), которая выводит на экран текст, заключенный в кавычки. Что и говорить, программа не из сложных.

Комбинация \n, передаваемая printf() при вызове программы, ≈ специальный символ перевода строки. Если вам приходилось работать в DOS, возможно, вы заметили, что в текстовых файлах DOS используется комбинация ⌠перевод строки/возврат курсора■, а в UNIX ≈ только перевод строки. Обратная косая черта (\) играет особую роль в программах на языке С. Обычно после нее указывается другой символ, и в сочетании с ним она дает непечатаемый символ (например, \n ≈ переход на новую строку, \t ≈ табуляция, \а ≈ звуковой сигнал и т. д.).

Параметры командной строки cc Многочисленные параметры управляют поведением команды cc и процессом исполняемых программ из текстовых файлов на языке С. Самые распространенные параметры командной строки cc перечислены в табл. 10.2. Таблица 10.2. Параметры командной строки cc
 
Параметр
Значение
-Iкаталог Заголовочные файлы ищутся в заданном каталоге и в /usr/include
имя_файла.с Компилирует файл имя_файла.с и строит объектный модуль имя_файла.о. Исполняемый файл при этом не создается
имя_программы Исполняемому файлу присваивается заданное имя. По умолчанию используется имя a.out
-g Компиляция с включением отладочной информации
-O (Буква O) Оптимизация программы для повышения быстродействия
-lбиблиотека (Буква l) Компоновка указанной библиотеки, содержащей заранее откомпилированные процедуры

  Большинство компиляторов UNIX не позволяет смешивать параметры -g (включение отладочной информации) и -O (оптимизация), однако компилятор С в Linux допускает такую возможность.

cc поддерживает много других параметров командной строки. Для их просмотра можно воспользоваться командой man cc.

Компоновка библиотек В программировании на С библиотекой (library) называется набор стандартных функций, которые могут использоваться в программах. Эти функции были предварительно откомпилированы с помощью cc и хранятся в специальных библиотечных файлах (library files). Если ваша программа, как и большинство других, не ограничивается стандартной библиотекой языка С, придется вручную скомпоновать (то есть подключить) необходимые библиотеки.

Если заглянуть в каталог /usr/lib, вы найдете в нем большинство библиотек, поддерживаемых Linux. В табл. 10.3 перечислены стандартные каталоги, в которых хранятся библиотеки Linux.

Таблица 10.3. Каталоги для библиотек Linux
 
Каталог
Библиотеки
/lib Базовые общие библиотеки (например, библиотека С)
/usr/lib Основные системные библиотеки
/usr/openwin/lib Библиотеки Open Look (например, библиотека Xview)
/usr/X11R6/lib Большинство библиотек Х Window

  Чтобы скомпоновать программу с библиотекой, воспользуйтесь параметром -l (буква l) командной строки cc. Так, для компоновки библиотеки X11 применяется команда -lХ11; это сокращенная форма для компоновки файла libX11.a (или эквивалентной общей библиотеки libX11.so). Разделяемые библиотеки Linux В Linux существует и такая замечательная концепция, как разделяемые библиотеки (shared libraries). Поскольку многие программисты используют очень большие библиотеки (особенно библиотеки Х Window), программы увеличиваются в размерах и занимают больше памяти (как физической, так виртуальной). Для решения этой проблемы в Linux появились общие библиотеки, похожие на библиотеки динамической компоновки (DLL) системы Windows. Идея заключается в том, чтобы несколько программ работали с одним экземпляром библиотеки, загруженным в памяти. Для программ Х Window таким образом экономится большое количество памяти.
Файлы ELF

В этой версии Linux используется формат объектных модулей ELF (Executable and Linking Format). Программы, откомпилированные в формате ELF, отличаются от тех, что были откомпилированы в старом формате a.out (название a.out не имеет отношения к стандартному имени исполняемых файлов, создаваемых командой cc). По сравнению со старым форматом ELF обеспечивает лучшую поддержку разделяемых библиотек, что и стало основной причиной для перехода на этот формат. Разделяемые библиотеки экономят память при одновременном запуске нескольких программ, особенно если это программы для Х Window.

Вам не придется беспокоиться об отличиях между ELF и a.out, за исключением одного факта: библиотеки a.out несовместимы с библиотеками ELF. Сказанное особо относится к разделяемым библиотекам.

Следовательно, ко всем полученным двоичным файлам Linux следует относиться с осторожностью. Если приложение компилируется на уровне исходных текстов, проблем не будет ≈ Linux использует библиотеки, присутствующие в вашей системе.

Но если приложение было получено заранее откомпилированным, придется убедиться в наличии необходимых библиотек, иначе программа просто не будет работать.

При установке Linux (или при любом последующем запуске sеtuр) можно установить библиотеки для обоих форматов, a.out и ELF. Если свободное место на диске позволяет, так и следует поступить. А если приходится ограничиться одним форматом, выбирайте ELF ≈ сейчас весь мир Linux переходит на ELF. Практически все компоненты Linux на прилагаемых CD-ROM также используют ELF, хотя присутствуют и старые библиотеки a.out.

Чтобы узнать, какие форматы поддерживаются компоновщиком ld, выполните следующую команду:

$ ld -v Результат будет выглядеть так: GNU Id version 2.8.2 (with BFD 2.8.1.0.23)
Supported emulations:
elf_i386
i386linux
i386coff
По умолчанию gсс компилирует программы в формат ELF. Чтобы проверить, вызовите команду file для любого исполняемого файла (например, для созданного ранее chap10): file chap10 На экране появляется следующая информация: chap10: ELF 32-bit LSB executable, Intel 80386,
version 1, dynamically linked, not stripped
Как и ожидалось, по умолчанию используется формат объектных файлов ELF.

К сожалению, термин a.out в разных контекстах принимает разные значения. Если откомпилировать программу командой gсс, по умолчанию выходному файлу присваивается имя a.out. Но даже этот файл a.out имеет объектный формат ELF, а не старый формат а.out. Иногда из-за этого возникают недоразумения.

Сейчас Linux переходит на формат ELF, поэтому трудности с форматами объектных файлов скоро исчезнут.


  У общих библиотек Linux имеется одна проблема ≈ они очень тесно связаны с номерами версий. При обновлении версии Linux многие старые приложения могут требовать старые версии общих библиотек, отсутствующие в вашей системе. Если у вас установлено много программ Linux, распространяемых только в двоичном формате, вам придется либо загрузить старые разделяемые библиотеки, либо дождаться обновления всех программ. Если у вас имеется исходный текст программы, достаточно заново откомпилировать и скомпоновать ее, и все будет в порядке.

Команда ldd выводит список разделяемых библиотек, необходимых для работы исполняемого файла. Например:

Idd /usr/local/bin/netscape
libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x4000a000)
libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0х40048000)
libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0х40050000)
libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0х40064000)
libXpm.so.6 => /usr/X11R6/lib/libXpm.so.6 (0х40075000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0х40084000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x4008e000)
libdl.so.1 => /lib/libdl.so.1 (0x4011f000)
libc.so.5 => /lib/libc.so.5 (0х40122000)
libg++.so.27 => /usr/ix86-linux/lib/libg++.so.27 (0x401de000)
libstdc++.so.27 => /usr/ix86-linux/lib/libstdc++.so.27 (0х40221000)
libm.so.5 => /lib/libm.so.5 (0х40264000)
Для каждой разделяемой библиотеки (например, libX11.so.6) в имени файла присутствует номер версии (6). Чтобы программа нормально работала, она должна найти каждую разделяемую библиотеку в заданных каталогах.
Программирование на C++ В дополнение к С Linux также поддерживает C++. Эта поддержка реализована тем же самым компилятором egcs.
Стандартная библиотека шаблонов(STL)

Linux поддерживает стандартную библиотеку шаблонов C++ (STL, Standard Template Library). Вы можете использовать в своих программах на C++ классы векторов, ассоциативных множеств, двухсторонних очередей и т. д., как в любой другой системе.

Версия STL в Linux была предоставлена Hewlett-Packard и Silicon Graphics. Linux поддерживает как старую версию с заголовочными файлами, имеющими суффикс .h (например, deque.h), так и новую версию, в которой эти суффиксы уже не используются. Заголовочные файлы находятся в каталоге /usr/include/g++.


  Традиционно в UNIX для компиляции программ на C++ использовалась команда СС, которая в Linux не поддерживается. Вместо этого следует вызывать команду c++ или g++ ≈ это одна и та же программа.

Параметры g++ и c++ практически совпадают с параметрами компилятора С, cc.

Программирование для Х В комплекте Linux поставляется несколько библиотек Х Window, которыми можно пользоваться как при самостоятельном программировании, так и при компиляции бесплатных приложений Х Window. Кроме того, в Linux входит LessTif ≈ бесплатная версия библиотек Motif, позволяющая компилировать Motif-программы. Библиотеки Motif необходимы практически для всех коммерческих приложений, использующих Х (коммерческие версии библиотек Motif можно приобрести у многих независимых фирм; подробности приведены в приложении А).

Как правило, компоновка программ Х не требует никаких особых действий, кроме включения библиотек Х в командную строку cc. Заголовочные файлы

X Window должны находиться на своем месте, в каталоге /usr/include/X11 (в действительности он является символической ссылкой на /usr/X11R6/include/X11, но для компилятора сойдет).

Следующая команда выполняет компиляцию и компоновку программы, использующей набор элементов Athena, который обеспечивает минимальный графический интерфейс для xman, xedit и xterm:

cc -о foo foo.с -L/usr/X11R6/lib -lXaw -lХt -lХ11 Параметр -l сообщает cc (а в действительности ≈ компоновщику ld, вызываемому cc) о необходимости компоновки указанной библиотеки. Перечисленные библиотеки обеспечивают работу некоторых общих функций. Библиотеки, перечисленные в нашем примере, предоставляют программам функциональные возможности X Window. Таким образом, параметр -lXaw приказывает ld скомпоновать библиотеку Xaw. По общепринятым правилам файл называется libXaw.a для статической библиотеки и libXaw.so для общей библиотеки. Эта библиотека обеспечивает работу пользовательского интерфейса в программах xedit и xterm ≈ интерфейса весьма примитивного. Среди других библиотек X, также обеспечивающих пользовательский интерфейс, ≈ XView и LessTif.

Библиотеки X Window хранятся в каталоге /usr/X11R6/lib. Параметр -L сообщает компилятору С о том, что просматривать нужно именно этот каталог. Если не указать местонахождение библиотек X, появляется следующее сообщение об ошибке:

/usr/i586-pc-linux-gnulibc1/bin/ld: cannot open -lXaw:
No such file or directory
collect2: ld returned 1 exit status
Если вы используете функции менеджера сеансов или Inter-Client Exchange, появившиеся в X11 версии 6, потребуются две дополнительные библиотеки: cc -о foo foo.с -L/usr/X11R6/lib -IXaw -IXt -lХ11 -lSM -lICE
LessTif Все хотят использовать библиотеки Motif, пока не выясняется, что это требует дополнительных расходов. К сожалению, Motif является коммерческим продуктом, а это означает, что вам за исходный код или двоичные файлы Motif придется платить отдельно. Добавьте к этому непостижимо сложную лицензию Motif для программистов, из которой почти невозможно понять, имеете ли вы право распространять свои приложения, ≈ есть от чего прийти в отчаяние.

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

LessTif является клоном библиотек Motif. Другими словами, это набор программных библиотек, которые выглядят и работают так же, как и библиотеки Motif (Xm и Mrm). В действительности эти библиотеки содержат совсем другой код, но с точки зрения программиста LessTif обладает тем же программным интерфейсом, что и Motif. LessTif поддерживает многие возможности Motif, и с каждой версией эта поддержка становится все более полной. При этом используются открытые заголовочные файлы с теми же именами, что и у прототипов Motif.

Программы, написанные для Motif, перекомпилируются для LessTif без модификации исходного текста ≈ по крайней мере, теоретически. Нам все же пришлось внести кое-какие изменения, учитывая тот факт, что на момент написания книги работа над LessTif еще не была закончена. К счастью, LessTif находится в процессе постоянного развития, поэтому сегодняшние проблемы со временем должны исчезнуть.

LessTif распространяется на условиях лицензии для библиотек GNU и может использоваться как в бесплатных, так и в коммерческих приложениях.

Компиляция LessTif Программы Motif используют библиотеку Xt (X Toolkit Intrinsics) подобно тому, как мы выше использовали элементы Athena. Чтобы откомпилировать и скомпоновать Motif-программу, воспользуйтесь командной строкой следующего вида: cc -о foo -I/usr/X11R6/include foo.c -L/usr/X11R6/lib -IXm -IXt -lХ11 Заголовочные файлы Motif находятся в каталоге /usr/X11R6/include, поэтому для компиляции Motif-программ имя этого каталога необходимо передать в командной строке с параметром -I.

Если вы используете функции менеджера сеансов или Inter-Client Exchange, появившиеся в X11 версии 6, потребуются две дополнительные библиотеки:

cc -о foo -I/usr/X11R6/include foo.c -L/usr/X11R6/lib -IXm -IXt -lХ11 -ISM -lICE
Диагностика проблем в LessTif Разработчики LessTif однозначно заявили, что LessTif ни в коем случае не является полноценным клоном Motif. На ранней стадии разработки LessTif это вполне естественно. Но невзирая на все, у LessTif есть много такого, что понравится программистам, работающим для Motif.

Как нетрудно предположить, у незаконченной бесплатной программы LessTif есть свои проблемы. Однако с каждой версией она становится лучше и лучше.

Если вы попытаетесь использовать LessTif для замены Motif в сложных Motif-программах, во время работы приложения могут появляться ошибки Х и Х Toolkit. Среди них ≈ ошибки Х BadMatch и BadValue, а также многие ошибки и предупреждения Х Toolkit, относящиеся к полосам прокрутки.

LessTif не всегда работает точно так же, как и Motif. Более того, программы, использующие внутренние функции Motif (с именами, начинающимися с _Хm), заведомо напрашиваются на неприятности с LessTif, потому что внутренний формат LessTif не полностью совпадает с форматом Motif (все-таки это разные библиотеки).

Если вы столкнетесь с проблемой, работая с LessTif (и уверены в том, что причина кроется в коде LessTif, а не в вашей собственной программе), обратитесь на Web-страницу LessTif по адресу http://www.lesstif.org/. Возможно, на ней уже имеется исправление. А если нет ≈ сообщите о проблеме, и исправление скоро появится.

Использование поддержки приложений Motif в Editres Editres ≈ приложение Х и одноименный протокол, с помощью которого программы, откомпилированные для библиотеки Х Toolkit Intrinsics (Xt), экспортируют информацию об атрибутах элементов во внешнюю программу (а именно, саму программу editres).

Если приложение поддерживает протокол editres, вы сможете воспользоваться editres и отредактировать шрифт, цвет и текст, отображаемый любым элементом. Для этого приложение должно создать функцию обработки событий и передать в качестве обработчика специальный библиотечный вызов _XEditResCheckMessages. Например, в следующем фрагменте создается функция обработки событий для приложения Motif:

#include <X11/Xmu/Editres.h>
Widget toplevel;
void _XEditResCheckMessages();
/*...*/
XtAddEventHandler(toplevel,
(EventMask) 0,
True,
_XEditResCheckMessages,
NULL);
После этого ваше Motif-приложение будет правильно реагировать на протокол editres.

Если вы используете функцию _XEditResCheckMessages, в процессе компоновки необходимо добавить еще одну библиотеку Х ≈ Xmu (сокращение от Х miscellaneous utilities, то есть ⌠разные утилиты X■). После добавления библиотеки команда сборки Motif-приложения принимает следующий вид:

cc -о foo -I/usr/X11R6/include foo.c -L/usr/X11R6/lib -IXm -IXmu -IXt -lХ11
Дополнительная информация о LessTif Посетите основную страницу LessTif в World Wide Web (www.lesstif.org/). Кроме того, последнюю версию LessTif можно взять с FTP-узла по адресу ftp: / /ftp.hungry.com/pub/hungry/lesstif/srcdist/.

За дополнительной информацией о программировании для Х и Motif обращайтесь в World Wide Web по адресу www.pconline.com/~erc/motif.htm.

XForms XForms ≈ библиотека С, кардинально упрощающая процесс создания программ для X. Главная задача XForms ≈ создание форм (в терминологии XForms этим термином обозначаются панели, простые или диалоговые окна). Форма в действительности представляет собой окно верхнего уровня, содержащее различные элементы. Упрощая этот процесс и предоставляя многочисленные стандартные варианты, XForms ликвидирует многие сложности, связанные с созданием приложений X. За это приходится расплачиваться снижением гибкости, но во многих ситуациях XForms оказывается идеальным решением.

В частности, свободой выбора приходится жертвовать в расположении элементов. Каждый элемент находится в строго заданной позиции, выраженной в пикселях, миллиметрах или пунктах (1/72 дюйма). В других наборах элементов (например, Motif) содержится широкий набор элементов, управляющих расположением других элементов. Конечно, расположение элементов является одним из самых сложных аспектов для разработчиков, не имеющих опыта работы с этой библиотекой. С другой стороны, XForms устраняет большую часть этих вариантов и соответствующих сложностей, непосредственно определяя позицию элементов.

XForms позволяет заполнить формы различными элементами ≈ кнопками, ползунками и текстовыми полями. Встречаются и более оригинальные элементы (например, циферблаты, часы и графики). Графики удобны для тех, кто захочет представить свои данные в графическом виде.

Хотя базовый набор элементов XForms кажется недостаточно полным, вы можете создавать ⌠произвольные■ (free) объекты, аналогичные элементу ⌠области рисования■ (drawing area) Motif, где ваше приложение получает пустой холст для рисования и функции обратного вызова для обработки всех событий. Тем самым открывается возможность расширения базового набора элементов. XForms содержит обширный интерфейс для добавления новых элементов.

Приложения XForms выглядят и ведут себя по-разному. Вы можете создавать кнопки различных типов, в том числе скошенные и с закругленными краями, поэтому интерфейс программы может напоминать Motif, Open Look и т. д.

Похоже, на внешний вид в немалой степени повлияли старые приложения Silicon Graphics. У многих элементов поддерживаются удобные стили границ, однако меню выглядят странно. Нам пришлось довольно долго привыкать к меню XForms; они ведут себя совсем не так, как в большинстве пакетов.

С другой стороны, XForms поддерживает различные шрифты и начертания текста, что очень удобно для тех, кто плохо разбирается в длинных именах шрифтов X. Благодаря разумному использованию шрифтовых стилей программа XForms может выглядеть значительно лучше большинства программ Motif, а объем кода будет существенно меньше.

Кодирование ≈ один из самых замечательных аспектов XForms. Работающее приложение можно создать очень быстро и с очень малым объемом кода.

XForms ≈ продукт, защищенный авторским правом и бесплатно распространяемый лишь для некоммерческих целей. Чтобы использовать XForms в коммерческом проекте, вы должны связаться с авторами XForms по адресу xforms@world.std.com. Очень важно, чтобы это правило соблюдалось.

XForms можно получить и в Интернете по адресу bragg.phys.uwm.edu/~zhao/ ftp/ftp.html. Основная страница XForms находится по адресу braag.phys.uwm.edu/xforms.

Инструментарий программиста Кроме базового компилятора Linux содержит много вспомогательных программ и утилит, упрощающих жизнь программиста. Первая и самая заметная из них ≈ программа make. Make Большинство программ на С состоит из нескольких исходных файлов (.с). При изменении одного из этих файлов необходимо перекомпилировать один (или более) из этих файлов, чтобы изменения отразились в исполняемой программе. Программисты от природы ленивы и не хотят перекомпилировать все файлы, если изменился только один. Более того, лентяи-программисты не желают следить за всеми изменившимися файлами. Им на помощь приходит утилита make.

Команда make помогает строить UNIX-программы из исходных файлов на языке С. Make использует набор правил, хранящихся в файле Makefile, для выбора наиболее эффективного способа построения программы. Файл Makefile присутствует в каждом каталоге, в котором создаются программы на С.

Makefile содержит набор правил с жестким синтаксисом, описывающих процесс построения программы. Большинство правил определяет, какая часть программы зависит от других частей. Используя эти правила зависимости, make определяет изменившиеся файлы (на основании даты их модификации) и компоненты, зависящие от этого файла или файлов. Затем make выполняет команды из Makefile и строит заново все необходимые компоненты.

Базовый синтаксис файла Makefile чрезвычайно прост. Linux содержит GNU-версию make, допускающую сокращенную запись некоторых правил. В этой главе мы лишь рассматриваем основы. Дополнительную информацию о make можно получить при помощи команды man make.

Прежде всего необходимо усвоить понятие ⌠цели■ (target). Целью называется то, что вы хотите построить, ≈ например, наша программа chap10 из предыдущего примера.

Чтобы создать новую цель в файле Makefile, начните новую строку и введите имя цели. Затем введите двоеточие и символ табуляции (Tab) и перечислите все файлы, от которых зависит данная цель. На следующей строке введите символ Tab и команду UNIX, используемую для построения цели. Таких команд может быть несколько, при этом каждая из них должна находиться на отдельной строке, начинающейся символом Tab.

Говоря о символе Tab, мы имеем в виду не последовательность пробелов, а именно этот символ. Make использует очень старый синтаксис, и для правильной работы утилиты необходимо присутствие символов Tab. В абстрактном виде содержимое Makefile выглядит так: что_строится: от_чего_зависит
команда1
команда2
командаЗ
последняя_команда
Выглядит весьма запутанно. Приведем более конкретный пример, основанный на программе chap10.

В данном случае целью является сама программа chap10. Цель зависит от объектного модуля chap10.o. При наличии объектного модуля chap10.o программа chap10 создается следующей командной строкой:

chap10:chap10.о
cc -о chap10 chap10.o
Согласно этому правилу, если файл chap10.o имеет более позднюю дату, чем chap10, следует выполнить команду cc для построения программы chap10 из объектного модуля chap10.o.

Но это лишь часть дела; мы также должны откомпилировать chap10.c, чтобы создать объектный модуль chap10.o. Иначе говоря, файл chap10.o зависит от файла chap10.c и строится на его основе. Для этого мы воспользуемся другим правилом make.

На этот раз объектный модуль chap10 зависит от текстового файла chap10.c. Команда построения объектного модуля выглядит так:

chap10.о:chap10.с
cc -с chap10.c
В результате редактирования chap10.c оказывается, что дата/время последней модификации этого файла позднее даты/времени объектного модуля chap10.o. Благодаря правилу make вызывается команда cc, которая компилирует chap10.c в chap10.o.

Секрет make несложен. Все зависит от даты/времени файлов ≈ очень простая, но умная концепция. Если текст программы изменился, необходимо построить программу с помощью cc. Но если файл программы остался прежним, компилировать его просто незачем (по крайней мере, в нашем примере).

Пример использования make Введите следующий текст в файл с именем Makefile: #
# Test Makefile
#
# The program chap10 depends on chap10.o.
chap10: chap10.o
cc -о chap10 chap10.o
# The object module chap10.o depends on chap10.c.
chap10.o: chap10.c
cc -c chap10.c
Этот файл должен находиться в том же каталоге, что и приведенный выше пример программы на С, chap10.c. Чтобы воспользоваться make, необходимо указать цель (то, что мы хотим построить). В нашем случае утилита make должна построить программу chap10. Построение программы осуществляется следующей командой: $ make chap10
cc -с chap10.с
cc -о chap10 chap10.о
Программа chap10 готова к выполнению. Если снова ввести команду make, она сообщает, что программа не изменилась и работы для нее нет: $ make chap10
chap10 is up to date
Почему? Потому что программа chap10 была только что построена и с момента ее построения ничего не изменилось. Теперь отредактируйте файл chap10.с или воспользуйтесь командой touch, чтобы изменить дату/время модификации файла: $ touch chap10.с При повторном запуске make утилита определяет, что на этот раз программу нужно построить заново, поскольку файл chap10.c изменился с момента последней компиляции chap10.c программой cc. Поскольку команда touch обновляет только дату/время файла и не изменяет его содержимого, мы, в сущности, обманули make. Утилита не проверяет, изменился ли сам файл. Она всего лишь сравнивает время последней модификации файла, наивно полагая, что никто не будет осуществлять запись в файл без изменения его содержимого. Впрочем, в нормальных ситуациях обманывать make незачем; простые правила этой утилиты упрощают вам жизнь.

Как видно из табл. 10.4, у make имеется несколько полезных параметров командной строки.

Таблица 10.4. Параметры командной строки make
 
Параметр
Значение
-f файл Вместо файла Makefile правила берутся из заданного файла
-n Запуск в ⌠холостом■ режиме, при котором команды только выводятся, но не выполняются
-s Подавление вывода ≈ команды, выполняемые make, не выводятся

  При компиляции бесплатных программ Linux в файлах Makefile часто встречаются специальные обозначения. Например, в большинстве файлов присутствует цель all, которая строит заново всю программу при выполнении команды: $ make all Чтобы эта команда работала, файл Makefile должен содержать цель с именем all и команды, которые должны выполняться для построения всей программы. Также во многих файлах Makefile встречается цель clean, которая удаляет объектные модули и другие файлы, созданные компилятором, и цель install, копирующая исполняемый файл в рабочий каталог (например, /usr/local/bin). Imake Кроме make существует и другая утилита ≈ imake. Она используется для построения файлов Makefile в различных системах. Правила imake хранятся в файле Imakefile и помогают сгенерировать файл Makefile, используемый для построения программы. Запутанно? Еще бы. Imake существует в первую очередь из-за кардинальных отличий в конфигурациях систем, особенно в том, что касается Х Window System. Например, в Linux большинство файлов Х находится в каталоге /usr/X11R6, но лишь немногие клоны UNIX следуют этому примеру. В результате написание программ (особенно программ для Х Window), которые должны работать в разных версиях UNIX, сопряжено со множеством проблем.

Утилита imake особенно часто используется в программах для Х Window System. Основная проблема Х заключается в многочисленных параметрах, из-за которых конфигурация каждой UNIX-платформы несколько отличается от остальных. Просто не существует способа написать переносимый файл Makefile, который будет работать на всех платформах UNIX. Imake использует файл Imakefile и локальные конфигурационные файлы вашей системы. Вместе они генерируют файл Makefile, который должен работать на вашем компьютере. Кроме imake существует еще более удобный пакет GNU configure. К сожалению, утилита imake широко распространена среди программ для Х Window, a configure ≈ нет.

Если в программе для Х Window System, которую вам понадобится откомпилировать, встретится файл Imakefile, действовать надо так. Прежде всего запустите сценарий оболочки xmkmf, который представляет собой простой интерфейсный модуль для imake:

$ xmkmf
mv Makefile Makefile.bak
imake -DUseInstalled -I/usr/lib/X11/config
Эти команды создают резервную копию имеющегося файла Makefile (в файле Makefile.bak) и затем создают новый вариант Makefile на основании команд Imakefile.

Освоить imake не так просто, поэтому при возникновении проблем с этой утилитой обратитесь к системному администратору или найдите описание imake в книге по Х Window System.

Как правило, imake чаще применяется для построения бесплатных приложений Х Window, нежели в ваших собственных проектах. В таком случае все, что от вас требуется, ≈ ввести упоминавшуюся выше команду xmkmf.

Отладчики Поскольку Linux прочно занимает свое место в мире программирования GNU, в системе присутствует как отладчик gdb, так и интерфейсный модуль для Х Window System xxgdb (рис. 10.1).
Рис. 10.1.Отладчик xxgdb

Утилиты X Window

Если вы занимаетесь разработкой приложений для Х Window, некоторые утилиты могут вам пригодиться. Программа xman (см. главу 3) обеспечивает графический интерфейс и удобное форматирование страниц электронной документации UNIX.

Простая утилита хсmар используется при отладке приложений X. Это простое приложение Х отображает текущее содержимое палитры. Для приложений X, интенсивно работающих с цветами, она часто помогает найти весьма запутанные проблемы.

Приложение xev выводит информацию о событиях, поступающих серверу Х с клавиатуры.

Утилиты xfd и xfontsel позволяют выбрать нужный шрифт для приложения.

Синтаксические и лексические анализаторы Если вы привыкли пользоваться собственными синтаксическими анализаторами, вам понравятся GNU-версии bison (перенесенный вариант ⌠компилятора компиляторов■ UNIX уасс ≈ Yet Another Compiler Compiler) и flex (fast lex). В Linux даже входит flex++ для языка c++. Помимо перечисленных утилит GNU, Linux содержит версии уасс и lex. Прочие утилиты В табл. 10.5 перечислены другие полезные утилиты для программистов. Таблица 10.5. Утилиты для программистов
 
Утилита
Использование
аr Объединение объектных файлов в библиотеки
diff Сравнение файлов
gprof Анализ временных показателей программ для настройки быстродействия
hexdump Вывод файла в формате ASCII, десятичной, шестнадцатеричной и восьмеричной системе счисления
objdump Вывод информации об объектном файле
ranlib Построение индекса для библиотеки, созданной командой аr
rcs Система контроля версий (Revision Control System)
strace Отображений вызовов системных функций из вашей программы

  Среди утилит даже существует программа ansi2knr, которая преобразует ANSI С в стандарт языка Кернигана-Рйтчи (без прототипов функций). В Linux она вам практически не понадобится, поскольку gсс в полной мере поддерживает ANSI С.

В табл. 10.5 перечислена лишь небольшая часть утилит. Вероятно, любая бесплатная утилита UNIX существует в версии для Linux.

Java Язык Java фирмы Sun ≈ один из самых модных новых языков, ориентированный на приложения World Wide Web. Программы, написанные на Java, компилируются в переносимый байт-код, который может выполняться на любом компьютере с поддержкой виртуальной машины Java. В каталоге /contrib/java CD-ROM присутствует версия Java для Linux ≈ Java Development Kit (JDK).

Во время написания книги каждые несколько месяцев появлялась новая версия Java. По этой причине вам стоит посетить сайты Java в Интернете и взять с них самые новые и потрясающие версии. Основной сайт, посвященный Java для Linux, ≈ www. black-down. org/java-linux.html.

Среди других полезных сайтов ≈ новости Java для Linux (www.w3com.com/ paulcho/javalinux/), а также советы и рекомендации по Java (www.parnasse.com/ java.shtml).

Другие языки программирования Универсальным языком программирования UNIX и Linux был и остается С, хотя в последнее время быстро набирает популярность C++ (объектно-ориентированное расширение С). Однако Linux не ограничивается этими языками и предоставляет в распоряжение программиста другие возможности.

Прежде всего, GNU-компилятор С egcs поддерживает Objective-C ≈ расширение языка С. Objective-C чрезвычайно популярен в среде NextStep. Компилятор С также поддерживает интерфейсный модуль для Fortran 77 (g77).

Для поклонников искусственного интеллекта имеется GNU Common Lisp (gcl).

По умолчанию в Slackware Linux не устанавливается ни один язык или утилита программирования. Соответствующие пакеты необходимо выбрать во время работы с программой setup.

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

Среди сценарных языков Linux наибольший интерес представляют Tcl, Perl и Python, хотя язык gawk также распространен достаточно широко.

Tcl Чрезвычайно удобный сценарный язык Tcl (Tool Command Language) поддерживается на большинстве UNIX-платформ и в Windows NT. Инструментальный пакет Тсl для Х Window (Tk) позволяет строить впечатляющие графические программы для Х Window ценой минимального кодирования.

Кроме того, Тс1 может внедряться в программы на С или C++, поэтому его можно использовать в качестве стандартного языка расширения в написанных вами электронных таблицах, играх или других программах.

Как правило, мы используем Тс1 для написания программ, которые имеют дружественный интерфейс пользователя, похожи на программы Motif и работают в широком диапазоне систем. Тс1 и пакет Tk отчасти воспроизводят внешний вид и поведение Motif ≈ для фанатиков недостаточно, но вполне хватает для большинства пользователей. Другое величайшее преимущество заключается в том, что Тс1 работает в системах Windows и MacOS, а также практически в любой разновидности UNIX.

Tcl ≈ язык написания сценариев, похожий на встроенные языки sh и bash, стандартных оболочек UNIX. Он имеет некоторые полезные средства для работы со строками и списками (точнее, списками строк ≈ в программе на Тс1 практически любой объект считается строкой).

Пакет Tk расширяет возможности Тс1. Он упрощает процесс создания элементов и организацию дружественного интерфейса в Х Window. Концепция элементов выглядит устрашающе, если вам не приходилось программировать с использованием множества инструментальных пакетов Х (например, Motif). Каждый элемент является частью пользовательского интерфейса программы (например, список файлов, кнопка выхода из программы и т. д.). Тот, кто работал с элементами Motif или Athena, быстро усвоит концепции Tk. Но даже если у вас нет опыта работы с библиотеками Motif или Athena, вы быстро разберетесь с азами Тс1 (впрочем, сложного в Тс1 тоже немало).

Пакет Tk, дополняющий Тс1, поддерживает большинство стандартных элементов, копирующих основные элементы Motif (кроме удобных элементов меню, комбинированного списка и записной книжки). В некоторых аспектах Тс1 превосходит Motif; особенно удобен элемент ⌠холст■ (canvas), на котором можно размещать графические ⌠объекты■ ≈ линии, прямоугольники, кривые Безье и даже другие элементы.

Сценарии Tcl В Тс1, как и во многих других сценарных языках, для получения значения переменной используется знак доллара ($). Тс1 работает только с текстовыми строками, поэтому возникает необходимость в специальном символе, который позволяет отличить строку от значения, хранящегося в переменной. Следовательно, variable ≈ это просто строка, состоящая из символов, a $variable ≈ значение, хранящееся в переменной с именем variable. Аналогичные правила используются в большинстве сценарных языков оболочек. Впрочем, это может привести к некоторым проблемам. По собственному опыту знаем, что простые опечатки (например, пропущенный символ $) становятся причиной большинства ошибок Тс1.

Например, если в переменной dir хранится имя каталога и вы хотите применить команду cd для перехода к этому каталогу, воспользуйтесь следующей командой Tcl:

cd $dir Базовый синтаксис Тс1 напоминает гибрид Lisp и С. Процедуры (обозначаемые словом рrос) похожи на функции С. Например: proc add_one { value } {
return [expr $value+1]
}
Фигурные скобки придают программе облик С. Сравнение с Lisp вызвано тем, что для присваивания вместо обычного символа = используется специальная команда set. Иначе говоря, оператор С а = b; в Тс1 будет выглядеть так: set a $b (Не забывайте о символе $, поначалу он может подвести вас.)

Одна из приятных особенностей Tcl ≈ возможность использования переменных в любой момент без их предварительного объявления (кроме массивов, которые должны быть объявлены перед их использованием в командах элементов).

Использование Tcl Чтобы познакомиться с практическим применением Тс1, запустите Tcl-интерпретатор wish. Он позволяет вводить команды Тс1 так, словно вы работаете в оболочке на базе Тс1 (чем, собственно, и является wish).

Одна из самых интересных возможностей Tcl ≈ создание графических программ с элементами (например, кнопками). Для создания кнопки в Тс1 используется следующая команда:

button .b1 \
-text "My first button" \
-command { exit }
Для продолжения команды на следующих строках можно воспользоваться символом \. Разделение строк упрощает чтение программы.

Приведенный выше фрагмент создает элемент-кнопку с именем .b1 (префикс-точка играет важную роль). Подобно тому, как символ \ используется в Linux для пометки корневого каталога, точка в Тс1 отмечает корневой элемент (главное окно приложения). Созданная нами кнопка расположена в иерархии под корневым элементом (по аналогии с подкаталогом, находящимся в другом каталоге).

Команда -command определяет команду Тс1, которая должна выполняться при нажатии кнопки. В нашем примере команда exit завершает работу wish и наш сценарий Тс1.

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

Найти такие ошибки бывает очень трудно. В программе-примере будут показаны некоторые обходные пути.

Чтобы элемент появился на экране, его необходимо упаковать командой pack. Команда pack вызывается с множеством параметров, включая имя элемента (или элементов):

pack .b1 Элементы Тс1 отображаются на экране только после упаковки.
Создание сценариев Tcl Набор команд Тс1 можно объединить в файле сценария, подобно тому, как это делается в сценариях оболочек С и Борна. Выполнение сценариев осуществляется программой wish. Следующий сценарий предполагает, что wish находится в каталоге /usr/bin (как в Linux).

Чтобы превратить пример в рабочий сценарий, мы делаем следующее:

#!/usr/bin/wish
#
# example.tcl
#
# Create a button
button .b1 \
-text "My first button" \
-command { exit }
pack .b1
#example1.tcl
Как и в любом сценарном языке, перед использованием сценария в качестве новой команды необходимо разрешить его исполнение командой chmod. Например, для сценария example.tcl используется следующая команда: $ chmod a+x example1.tcl Чтобы лучше продемонстрировать особенности программирования на Tcl, мы написали еще один сценарий. В нем команды Tcl создают набор кнопок для запуска полезных программ Linux (например, xman или xterm). Панель с кнопками находится в верхней части экрана и использует специальный режим, который не позволяет менеджеру окна создать над окном заголовок. Кроме того, по традиции Windows в конце панели выводится текущее время.

В нашем сценарии создается несколько процедур (ключевое слово рrос). Процедура exec_cmd выполняет команду UNIX, заданную в виде текстовой строки. Для работы со строками и вычисления значений переменных используется команда eval. Попробуйте убрать eval из процедуры exec_cmd и запустить сценарий ≈ вы поймете, зачем нужна эта команда (она связана с передачей аргументов в командной строке; в этой области Tcl трудно понять на интуитивном уровне).

Процедура update_time с помощью команды Tcl clock получает текущее время и изменяет текст, отображаемый в элементе (имя элемента передается update_time в качестве аргумента). Затем команда after создает функцию обратного вызова, чтобы организовать вызов процедуры update_time после заданного промежутка времени.

Главная часть сценария Tcl создает элемент-рамку (frame), где будут находиться кнопки, после чего создает набор кнопок. При нажатии кнопки со словом Linux и хостовым именем вашего компьютера работа сценария завершается.

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

Таблица 10.6. Приложения, запускаемые из сценария tooLbar.tcl
 
Кнопка
Приложение
Manuals xman ≈ просмотр электронной документации Linux
Mail elm (в окне xterm) ≈ чтение почты
Shell xterm ≈ окно с оболочкой командной строки
File Manager xfm ≈ менеджер файлов Linux
Images xv ≈ программа просмотра графических файлов

  Ниже приведен сценарий Тс1, который все это делает. #!/usr/bin/wish
#
# toolbar.tcl
# Сценарий Tcl, создающий в нижней части экрана
# панель для запуска программ.
#
# Процедура выполняет команду как процесс UNIX.
#
proc exec_cmd { command } {
# Выполнить как процесс UNIX в фоновом режиме.
# Мы используем eval, чтобы избавиться от хлопот
# по разделению команды на составные части
# (попробуйте убрать eval и поймете, для чего нужна)
#
eval exec $command &
}
#
# Процедура Tcl/Tk для вывода текущего времени в элементе
set title_interval 40000
global title_interval
proc update_time { butn } {
global title_interval
# Получить текущее время,
set timestr [clock format \
[clock seconds] -format "%I:%M %p"]
$butn config -text $timestr
# Организовать повторное выполнение команды
after $title_interval "update_time $butn"
}
#
# Глобальные команды,
# выполняемые при нажатии кнопок панели
#
set cmds(man) "/usr/bin/x11/xman -notopbox -bothshown"
set cmds(mail) "/usr/bin/X11/xterm -ls -e elrn"
set cmds(term) "/usr/bin/X11/xterm -ls"
set cmds(file) "/usr/bin/x11/xfm"
set cmds(image) "/usr/bin/bin/xv"
# Сделать массив cmds глобальным
#
# Главная программа
#
# Задать параметры менеджера окон.
wm geometry . +0+0
wm overrideredirect . true
#
# Рамка, в которой находятся кнопки
#
set back lightgray
frame .frame -relief raised -bd 2 -bg $back
.frame config -cursor top_left_arrow
#
# Кнопка выхода
#
set title [format "Linux: %s" [exec hostname ] ]
button .frame.logo -text $title \
-command { exit } -bg $back \
-relief flat -padx 8
pack .frame.logo -side left -fill у
#
# Остальные кнопки на панели
#
button .frame.man -text "Manuals" \
-command { exec_cmd $cmds(man) } \
-relief flat -padx 8 -bg $back
button .frame.man -text "Mail" \
-command { exec_cmd $cmds(mail) } \
-relief flat -padx 8 -bg $back
button .frame.man -text "Shell" \
-command { exec_cmd $cmds(term) } \
-relief flat -padx 8 -bg $back
button .frame.man -text "File Manager" \
-command { exec_cmd $cmds(file) } \
-relief flat -padx 8 -bg $back
button .frame.man -text "Images" \
-command { exec_cmd $cmds(image) } \
-relief flat -padx 8 -bg $back
# Упаковка всех кнопок в заданном порядке
pack .frame.man .frame.mail \
.frame.term .frame.file .frame.image \
-side left -fill у
# Настройка таймера
label .frame.time -bg $back
update_time .frame.time
pack .frame.time -side left -fill у
pack .frame
# Конец файла toolbar.tcl
Вы можете легко добавить на панель собственные кнопки. Делается это так:

1. Включите в блок set cmds нужную команду UNIX.

2. В блоке button скопируйте команду создания одной из кнопок. Замените имя кнопки на frame, yourname или что-нибудь в этом роде. Кроме того, проследите за тем, чтобы при нажатии кнопки использовалась команда из блока set cmds.

3. Включите в команду pack, расположенную сразу же после блока buttons, имя вашей кнопки.

Эти два примера помогут вам начать самостоятельную разработку сценариев на Тс1. Как упоминалось выше, одна из самых замечательных особенностей Тс1 заключается в том, что этот язык также поддерживается системами Windows и Macintosh.

Perl Perl ≈ бесплатно распространяемый язык написания сценариев, разработанный для решения задач системного администрирования. Сокращение Perl происходит от слов Practical Extraction and Report Language. Язык предназначен в первую очередь для извлечения данных из отчетов UNIX ≈ например, из отчетов об использовании диска новостями Usenet или списка всех пользователей вашей системы, отсортированного по объему занимаемого места на диске (Perl лучше всего проявляет себя в задачах, связанных с обработкой системной информации). Из-за его развитых возможностей обработки текста практически все Web-формы используют Perl для обработки введенных данных.

Чтобы проверить, был ли установлен Perl при установке Linux, введите следующую команду:

$ perl -v Если Perl присутствует в системе, на экране появляется номер версии. А если нет, придется снова запустить программу setup (которая устанавливает Perl 5.004_04).
Пример сценария на Perl В Perl, как и Тс1 и других сценарных языках Linux, символ # используется для обозначения комментариев. Начиная с символа #, содержимое любой строки игнорируется. Для вывода данных в сценариях Perl используется команда print: #! /usr/bin/perl
print "Linux runs Perl!\n";
print "Oh, joy!\n";
Если запустить этот сценарий, результат выглядит так: Linux runs Perl!
Oh, joy!
Символ \n обозначает переход на другую строку и принадлежит к числу стандартных обозначений UNIX, упоминавшихся в разделе по программированию на языке С.

Perl также позволяет запросить данные у пользователя, при этом используется несколько странный синтаксис:

#! /usr/bin/perl
print "What is your first name: ";
# <STDIN> означает стандартный ввод - клавиатуру.
$first_name = <STDIN>;
# Удалить завершающий символ перевода строки
chomp($firstname);
printf "What is your last name: ";
$last_name = <STDIN>;
chomp($lastname);
print "Your паше is $firstname $lastname.\n";
# askname.pl
Если запустить этот сценарий, результаты будут выглядеть так: What is your first name: Eric
What is your last name: Foster-Johnson
Your name is Eric Foster-Johnson.
Массивы, управление процессами и обработка строк В Perl реализованы массивы, а также возможности управления процессами UNIX и обработки строк. Массивы Perl позволяют интерпретировать набор данных в виде одного целого, например: (1,2,3,4,5,6) В этом массиве хранятся числа от 1 до 6. Массив также может содержать смешанные текстовые и числовые значения: (1, 2, 3, 4, "Linux is out the door") Такой массив можно присвоить переменной, а затем обратиться к его произвольному элементу. К числу самых замечательных возможностей Perl относятся ассоциативные массивы, или хэши (hashes) ≈ в таких массивах в качестве индекса используется ключ, который ассоциируется с некоторой величиной. Предположим, вы создали массив Perl для хранения имен, фамилий и адресов. После этого адрес можно получить следующим образом: #! /usr/bin/perl
# Ассоциативные массивы (хэши) в Perl
# Массив zippy является ассоциативным
$zippy{"firstname"} = "Zippy";
$zippy{"address"} = "1600 Pennsylvania Ave.";
# Вывести данные.
print $zippy{"firstname"};
print "'s address is ";
print $zippy{"address"};
# Завершающий перевод строки
print "\n";
# assoc.pl
В этом примере имя и адрес хранятся в ассоциативном массиве zippy. Ассоциативные массивы обладают чрезвычайно широкими возможностями и эффективно применяются во многих задачах системного администрирования.

Вывод предыдущего сценария выглядит примерно так:

Zippy's address is 1600 Pennsylvania Ave. В Perl также имеется множество команд форматирования текста, упрощающих построение отчетов (исходная причина разработки Perl). Язык Perl тесно связан с UNIX и содержит средства выполнения стандартных операций UNIX ≈ например, для работы с файлом паролей, как показано в следующем примере: #! /usr/bin/perl
# Работа с файлом паролей.
# Получить информацию из /etc/passwd об Эрике и вывести ее.
getpwnam("erc");
($username, $realname, $homedir) = @erc_entry[0,6,7];
print "User $realname has";
print " a home directory of $homedir";
print " and a username of $username.\n";
# passwd.pl
Результаты запуска этого сценария выглядят примерно так: User Eric Foster-Johnson,,, has a home directory of /usr2/erc and a
username of erc.
Естественно, вы должны использовать имя пользователя для вашей системы. Три запятые (,,,) появляются из файла /etc/passwd. В записях пользователей, добавленных посредством сценария adduser, присутствуют три запятые.

Конечно, Perl обладает множеством других возможностей, и об этом языке написано немало книг. Если вам захочется больше узнать о Perl, обращайтесь к приложению А.

Python Язык Python получил свое название в честь телевизионного шоу ⌠Цирк Монти Пайтона■. Это объектно-ориентированный сценарный язык, исходный вариант которого был разработан Гвидо ван Россумом (Guido van Rossum). Одна из его отличительных особенностей ≈ использование пробелов и отступов для группировки команд.

Как нетрудно догадаться, сценарии Python выполняются командой python.

Обучающее руководство по Python имеется в Web (www.python.org/doc/ tut/tut.html). Основной сайт Python расположен по адресу www.python. org/.

Gawk Язык awk разработали трое ученых из Bell Labs ≈ Альфред Ахо, Питер Вайнбергер и Брайан Керниган, отсюда и сокращение awk. Awk является языком программирования (и обладает значительным сходством с С), однако используется почти так же, как и другие сценарные языки UNIX, поэтому он и был включен в эту главу.

Строго говоря, в составе Linux поставляется не awk, а его GNU-версия, gawk (вероятно, вы уже привыкли к тому, что в Linux включаются программы из проекта GNU). Gawk практически идентичен с другими реализациями awk (в gawk существуют некоторые дополнения, но при желании их можно игнорировать), поэтому пользователи с опытом работы на awk смогут без труда перейти на gawk.

Обработка структурированных текстовых файлов Главная область применения gawk ≈ обработка структурированных текстовых файлов, где информация упорядочивается по столбцам и разделяется одинаковыми символами (например, символами табуляции или пробелами). Gawk выполняет в таких файлах различные операции ≈ редактирование, сортировку и поиск.

Для примера возьмем файл данных workers:

Eric 286 555-6674 егc 8
Geisha 280 555-4221 geisha 10
Kevin 279 55-1112 kevin 2
Tom 284 555-2121 spike 12
Давайте попробуем мыслить абстрактно и представим себе файл в виде двумерной таблицы. Каждая строка файла называется записью и состоит из полей (столбцов), почти как база данных. Gawk позволяет обрабатывать данные файла по строкам или по столбцам. Использовать команды gawk несложно. Команда gawk имеет следующую структуру: $ gawk [параметр] 'шаблон {действие}' В gawk допустимы всего три параметра. Параметр -F позволяет выбрать символ-разделитель полей взамен принятых по умолчанию. Параметр -f позволяет указать имя файла с командами gawk, вместо того чтобы включать сложные шаблоны и действия в командную строку Linux. Наконец, параметр -W заставляет gawk работать в режиме полной совместимости с awk.

Давайте определимся с терминологией. Образцы (patterns) могут представлять собой ASCII-строки (которые интерпретируются в числовом виде ≈ вместо символов используются числовые ASCII-эквиваленты), числа, комбинации чисел с возможным применением символов подстановки. Действие определяет выполняемые команды. В сущности, работа gawk построена на поиске заданного образца; если образец будет найден, gawk делает с ним что-то полезное (например, выводит его в другой файл).

Простейшая программа gawk просто выводит все содержимое файла:

$ gawk '{ print }' workers
Eric 286 555-6674 erc 8
Geisha 280 555-4221 geisha 10
Kevin 279 55-1112 kevin 2
Tom 284 555-2121 spike 12
Предположим, нам понадобилось отобрать все записи, начинающиеся со строки geisha. Для этой цели используется следующая команда: gilbert:/$ gawk '$1 ~ /Geisha/ { print $0}' workers Ниже подробно описывается смысл этой команды:
В нашем примере gawk выведет на экран следующую строку: Geisha 280 555-4221 geisha 10 Конечно, возможен не только точный поиск. В gawk тильда (~) представляет собой оператор отношения, определяющий условие поиска. В gawk существуют и другие операторы отношения, предназначенные для сравнения двух шаблонов (операторы отношения основаны на алгебраической записи). В Gawk поддерживаются те же операторы отношения, что и в языке программирования С; они перечислены в табл. 10.7. Таблица 10.7. Операторы отношения gawk
 
Оператор
Значение
Применение
< Меньше $1<"Еriс" возвращает все поля, меньшие "Eric" (по ASCII-кодам)
<= Меньше или равно $1<="Еriс" возвращает все поля, меньшие или совпадающие с "Eric"
== Равно $1=="Eric" возвращает все экземпляры "Eric"
!= Не равно $1!="Eric" возвращает все поля, не содержащие строки "Eric"
>= Больше или равно $1>="Еriс" возвращает все поля, большие или совпадающие с "Eric"
> Больше $1>"Еriс" возвращает все поля, большие "Eric"

  Существует несколько возможностей усложнить поиск в gawk. Во-первых, допускаются составные условия поиска, в которых используются три логических оператора: Допустим, нам понадобилось узнать, в каких записях значение пятого поля больше либо равно 10: $ gawk '$5 >= 10 { print $0 } ' workers
Geisha 280 555-4221 geisha 10
Тоm 284 555-2121 spike 12
Объединяя условия проверок, мы можем определить все записи, у которых значение пятого поля меньше 10, а значение второго ≈ больше 280: $ gawk '$5 < 10 && $2 > 280 { print $0 } ' workers
Eric 286 555-6674 erc 8
Конечно, приведенные примеры условны, но на практике gawk можно использовать для отбора всех записей с одинаковыми почтовыми индексами или всех работников с окладами, лежащими в определенном интервале. Впрочем, мы лишь едва соприкоснулись с gawk.

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

$ gawk '$1 ~/Eric/,/Kevin/ { print $0 }' workers
Eric 286 555-6674 erc 8
Geisha 280 555-4221 geisha 10
Kevin 279 55-1112 kevin 2
Если вас интересует не вся запись, можно ограничиться выводом отдельных полей. Так, в следующем примере выводится второе и первое поля: $ gawk '$1 ~ /Eric/,/Kevin/ { print $2, $1 }' workers
286 Eric
280 Geisha
279 Kevin
Команда gawk, как и все остальные команды UNIX, может использоваться в конвейерах, а ее результаты ≈ направляться в файл или непосредственно на принтер. Например, если вы просматриваете большой файл и ожидаете найти много экземпляров некоторой строки (например, записей из определенного интервала окладов или дат найма), полученные данные будет удобнее записать в файл или вывести на принтер.

Приведем пример использования команды gawk в сочетании с утилитой Linux sort:

$ gawk '$1 ~ /Eric/,/Kevin/ { print $2, $1 }' workers | sort
279 Kevin
280 Geisha
286 Eric
(сортировка по числовому коду в начале строки).

Gawk также обладает некоторыми возможностями для сбора статистики. Так, символ NR в команде gawk возвращает общее количество записей.

Мы используем эту возможность в программе, написанной для gawk.

Программы gawk Возможности gawk не ограничиваются объемом командной строки. Серию команд gawk можно записать в файл, а затем выполнить этот файл с помощью gawk.

Давайте запишем простейшую команду gawk, {print}, в отдельный файл и выполним его командой gawk:

$ gawk -f gawk.1 workers
Eric 286 555-6674 егc 8
Geisha 280 555-4221 geisha 10
Kevin 279 55-1112 kevin 2
Tom 284 555-2121 spike 12
Предполагается, что файл gawkl содержит простейшую программу gawk: { print } Команды BEGIN, END и NR используются для построения более сложных программ gawk. Используя их, необходимо помнить о том, что каждая команда gawk применяется к каждой записи (то есть к каждой строке) входного файла. Например, команда { print } выводит все содержимое входного файла.

Команда BEGIN определяет действия, которые должны выполняться перед чтением текста. Например:

BEGIN { print "Workers for Spacely Sprockets"; print "" }
{ print }
Эта программа печатает текст Workers for Spacely Sprockets перед тем, как выводить содержимое всех строк файла workers. При этом командная строка должна выглядеть следующим образом (при условии, что программа находится в файле gawk.2): $ gawk -f gawk.2 workers
Workers for Spacely Sprockets
Eric 286 555-6674 erc 8
Geisha 280 555-4221 geisha 10
Kevin 279 55-1112 kevin 2
Tom 284 555-2121 spike 12
Команда print "" выводит пустую строку.

Команда END выполняется после того, как все данные будут прочитаны. Именно здесь бывает удобно воспользоваться командой NR (количество записей):

BEGIN { print "Workers for Spacely Sprockets"; print "" }
{ print }
END { print "There are ",
NR,
" employees left after the latest wave of layoffs." }
Форматирование в секции END использовано только для ясности. Команды могут располагаться и в одной строке, это никак не повлияет на выводимые результаты. Запишите программу в файл gawk.3 и выполните следующую команду: $ gawk -f gawk.3 workers
Workers for Spacely Sprockets
Eric 286 555-6674 erc 8
Geisha 280 555-4221 geisha 10
Kevin 279 55-1112 kevin 2
Tom 284 555-2121 spike 12
There are 4 employees left after the latest wave of layoffs.
В этом кратком обзоре вы познакомились с gawk на самом простейшем уровне. Однако gawk обладает многими возможностями полноценных языков программирования: циклы, переменные, обработка строк и чисел, а также создание массивов и операции с ними. Если вы хотите относительно быстро освоить полезный язык программирования, мы рекомендуем поближе познакомиться с gawk.
Итоги Конечно, большинство читателей составляют программисты, потенциальные или практикующие. Поэтому мы рассмотрели многие средства программиста, имеющиеся в Linux. Однако в своем обзоре мы лишь едва затронули возможности программирования в Linux ≈ как для традиционных текстовых приложений, так и для программ, работающих в Х Window System.

Глава началась с обсуждения gсс, GNU-компилятора С, поставляемого вместе с Linux. Gcc позволяет компилировать программы на С, C++ и Objective-C. Вы узнали о коротком и длинном вариантах компиляции, а также познакомились с утилитой make.

Далее мы рассмотрели программирование для Х Window System и необходимые для этого программные библиотеки. Бесплатная библиотека LessTif заменяет коммерческие библиотеки Motif. Конечно, работа над LessTif еще не закончена, однако проект вполне заслуживает включения в поставку Slackware Linux, а также внимания программистов, занимающихся программированием для Motif.

Также вы узнали о команде imake, которая применяется при компиляции многих приложений Х в различных операционных системах.

Язык сценариев Tcl/Tk позволяет создавать Motif-подобные интерфейсы на относительно простом сценарном языке. Мы привели пример сценария, который создает на экране панель для запуска приложений.

Популярности замечательного языка Perl способствует его широкое распространение в Интернете. Впрочем, его разносторонние возможности пригодятся и тем, кто не имеет никакого отношения к Интернету.

Python ≈ еще один язык, также приобретающий популярность в последнее время.

Не приходится удивляться и тому, что в Linux входит еще одна программа из проекта GNU ≈ gawk, функциональный аналог языка программирования awk. Самой сильной стороной gawk является обработка структурированной информации, хотя этот язык обладает и другими возможностями современных языков программирования.