Rambler's Top100 Service калинин.ru / программирование / c и c++ /  << 16.10.00 >>

ploticus

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

Нет, таких программ великое множество, но ploticus отличается от них, как это мне сегодня объяснили, очень удобным преимуществом: он "глупый". То есть, его можно, например, заставить разместить надпись на рисунке с точностью до пикселя... иногда это нужно.

Но разговор не об удобстве этой программы. Просто "нам" (в смысле, конторе, где я сейчас работаю), потребовалось нечто подобное. Было решено использовать ploticus, но при этом немного доработанный напильником. Программист, который этим напильником орудовал, сегодня пребывал в особенно веселом настроении... почему --- ниже.

Сначала немного лирики. Ploticus, для того, что бы построить график, читает некоторый файл, в котором находится определение этого самого графика (скрипт, так сказать). Этот файл обладает очень простой грамматикой. Мало того, ploticus умеет организовывать программный канал (хотя, кто этого не умеет?) и читать данные оттуда, как результат выполнения другой программы.

Так вот о чтении этого файла я и хочу немного рассказать. Просто, программиста, который занимается работой с ploticus'ом, настолько поразила организация этого "счастья", что он сегодня к концу рабочего дня был уже совсем "не в себе" и занимался тем, что показывал избранные куски кода проходящим мимо людям.

Итак, подпрограммы чтения данных в ploticus разбиты на некоторые логические блоки, исходя из структуры самого файла с данными. Ну это понятно и логично. Не особенно понятно другое: каждая подпрограмма (парсер) на вход воспринимает название файла, в котором находится содержимое. В итоге, основная подпрограмма сначала разбивает файл на блоки, содержимое этих файлов копирует (!) во временные файлы (!!), которые подсовывает на вход другим подпрограммам. Это, конечно, уже достаточно оригинально, хотя задумка автора ясна --- он хотел сделать так, что бы в этих местах на вход подпрограммам чтения данных можно было бы подсунуть имя программы, которая эти данные бы сгенерировала. Тем не менее, можно было бы сделать значительно красивее, чем создавать кучу временных текстовых файлов.

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

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

Все написанное выше уже смешно. Но кусочек кода, который я сейчас приведу, довел программиста до истерического смеха. Вот он (с купюрами):

/*
 * ...
 */
else if( stricmp( attr, "data" )==0 ) {
	FILE *tfp;
	sprintf( datafile, "%s_D", Tmpname );
	getmultiline( "data", lineval, fp, MAXBIGBUF, Bigbuf );
	tfp = fopen( datafile, "w" );
	if( tfp == NULL ) return( Eerr( 294, "Cannot open tmp data file", datafile ));
	fprintf( tfp, "%s", Bigbuf );
	fclose( tfp );
	}
/*
 * ...
 */

Это как раз и есть выделение секции с данными и запись ее во временный файл. Вообще, использование fprintf с шаблоном "%s" уже смотрится очень оригинально, но то, что идет 80 строками ниже еще более необычно:

/*
 * ...
 */
if( standardinput || strcmp( datafile, "-" ) ==0 ) 
{ /* a file of "-" means read from stdin */
	dfp = stdin;
	goto PT1;
	}
if( strlen( datafile ) > 0 ) sprintf( command, "cat %s", datafile );
if( strlen( command ) > 0 ) {
	dfp = popen( command, "r" );
	if( dfp == NULL ) {
		Skipout = 1;
		return( Eerr( 401, "Cannot open", command ) );
		}

	PT1:
/*
 * ...
 */

Прошу обратить внимание на строчку:

if( strlen( datafile ) > 0 ) sprintf( command, "cat %s", datafile );

и следующую за ней

	dfp = popen( command, "r" );

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

	dfp = stdin;
	goto PT1;

В общем, дикость. Если кто-то не понял, то объясняю то, что происходит, на пальцах: читается секция "data" и ее содержимое записывается в файл, название которого содержится в datafile. Потом, проверяется название этого файла, если оно равно "-", то это значит, что данные ожидаются со стандартного файла ввода, stdin. Если же нет, то проверяется длина строки, на которую указывает datafile. Если она ненулевая, то считается, что команда, результаты работы которой будут считаться за входные данные, это "cat datafile". Если же ненулевая длина у другого параметра, command, то его значение принимается за выполняемую команду. После всех этих манипуляций, открывается программный канал (pipe) при помощи popen(), результатом которой является обычный указатель на структуру FILE (при его помощи можно использовать обычные средства ввода-вывода).

Вам это не смешно?

Резюме

Иногда лучше всего не заглядывать внутрь используемых программ... что бы не расстраиваться.


Версия для печати


  Ссылки по теме:
http://www.sgpr.net
   Официальная страница программы ploticus.
/comment/books/27_08_00.html
   C и C++. Правила программирования.
  Рядом в разделе:
Религия и goto (14.04.01)
   Начнем несколько издалека. В программировании существует тенденция к алгоритмизации самого процесса программирования. То есть, выведение некоторых универсальных правил, использование которых в...   >>>>
Шаманство, или ошибки работы с памятью (25.09.00)
   Когда программа становится внушительной по своему содержанию (то есть, не по количеству строчек, а по непонятности внутренних связей), то ее поведение...   >>>>
  Рядом по дате:
Хостинг (19.10.00)
   Как я уже намекнул в предыдущей заметке, я искал себе новый хостинг. Хочу сразу же сказать, что я его себе, вроде...   >>>>
Новый дизайн (14.10.00)
   Я раньше не понимал фраз типа "содержание выросло из оформления", пока две недели назад не попытался просто полистать свою страничку. Вы...   >>>>
  Содержание:
Заглавная страница
Мой блог
Мое резюме
Дайджест
Программирование
   C&C++
Сети
Unix
Алгоритмы
Оптимизация
Соревнования
Отвлеченно
XML
TeX
Просто так
Студенческое
Туризм
  Байки
Фотографии
Комментарии
   Книги
Web-ресурсы
Фильмы
Интернет
Программное обеспечение
Жизнь
Благодарности
Форум
Хронология
 
  В этом разделе:
Простой, но полезный аллокатор памяти (18.02.03)
   Эта заметка --- продолжение "Postfix изнутри" в том смысле, что в качестве примера опять берется postfix. Но если в прошлый раз...   >>>>
C или C++? (09.07.01)
   Существуют два диаметрально противоположенных, но одинаково распространенных мнения, которые можно выразить как "C++ это C с классами" и "C++ и C...   >>>>
Религия и goto (14.04.01)
   Начнем несколько издалека. В программировании существует тенденция к алгоритмизации самого процесса программирования. То есть, выведение некоторых универсальных правил, использование которых в...   >>>>
ploticus (16.10.00)
   Есть такая программа, предназначенная для создания графиков различных видов из командной строки, называется ploticus. Программа сама по себе достаточно удобная ---...   >>>>
Шаманство, или ошибки работы с памятью (25.09.00)
   Когда программа становится внушительной по своему содержанию (то есть, не по количеству строчек, а по непонятности внутренних связей), то ее поведение...   >>>>
Библиотека консорциума W3, libwww (20.09.00)
   Популярный нынче термин "веб-программирование" обычно подразумевает под собой программирование, в лучшем случае, на perl, в худшем --- на PHP, в совсем...   >>>>
Инварианты внутри программы (18.09.00)
   Вы когда-нибудь задумывались, над тем, как вы пишите программы? Если нет, то, я думаю, сегодняшняя заметка будет вам полезна. Итак, как...   >>>>
Содержание раздела полностью...
   Примерно в тоже время
Хостинг (19.10.00)
   Как я уже намекнул в предыдущей заметке, я искал себе новый хостинг. Хочу сразу же сказать, что я его себе, вроде...   >>>>
Новый дизайн (14.10.00)
   Я раньше не понимал фраз типа "содержание выросло из оформления", пока две недели назад не попытался просто полистать свою страничку. Вы...   >>>>
Хронология полностью...
   Содержание
Заглавная страница
Мой блог
Мое резюме
Дайджест
Программирование
  C&C++
Сети
Unix
Алгоритмы
Оптимизация
Соревнования
Отвлеченно
XML
TeX
Туризм
  Байки
Фотографии
Комментарии
  Книги
Web-ресурсы
Фильмы
Интернет
Программное обеспечение
Жизнь
Студенческое
Просто так
Благодарности
Форум
Хронология
© 2000-2008, Andrey L. Kalinin
mailto:andrey@kalinin.ru
Rambler's Top100