В статье приведена спецификация модуля HTML::Phl для работы с HTML-документами, содержащими код языка программирования Perl.
Задача модуля HTML::Phl — выбрать из текстового документа формата HTML, размещенный в нем особым образом perl-код, выполнить кое-какие манипуляции над ним и остальным кодом, объединить полученное в единый код perl и «скормить» всё это ‘eval‘, получая на выходе сгенерированную HTML-страницу, воспроизводимую веб-браузером.
1 <HTML> 2 <HEAD> 3 <META content="text/html; charset=UTF-8" http-equiv="Content-Type"> 4 <TITLE>Пример PHL</TITLE> 5 </HEAD> 6 7 Создаем два дочерних процесса f1 и f2<br> 8 9 %pl include("process_win.phl", "fork decode=cp1251", "f1"); 10 %pl include("process_utf.phl", "fork decode=utf8", "f2"); 11 12 Ждем завершения процессов<br> 13 14 <%pl my %join = include("JOIN", "f1 f2"); %> 15 16 Результаты выполнения процессов<br> 17 18 <%pl 19 foreach my $key(keys(%join)) { 20 if (ref $join{$key}) { 21 print "процесс '$key' - результат: "; 22 for (my $i = 0; $i <= $#{$join{$key}}; $i++) { 23 print "'${$join{$key}}[$i]' "; 24 } 25 print "<br>"; 26 } else { 27 print "процесс '$key' - результат: '$join{$key}'<br>"; 28 } 29 } 30 %> 31 32 </HTML>
Статья написана в ознакомительных целях, разработка модуля носит концептуальный характер, и его надежное применение нуждается в дополнительном тестировании.
Оглавление:
Спецификация PHL
• Указатели
• Разделители
• Ключи
• Функции
• Модули-расширения
• Конфигурационные настройки
Дистрибутив PHL
Спецификация PHL ^
В HTML документе perl-код размещается с помощью своеобразных инструкций. У каждой такой инструкции есть начало и конец, позволяющие идентифицировать код perl в документе.
В спецификации PHL определено три варианта написания инструкций:
1. Линейная инструкция:
%pl [keys] [perl code]
2. Инструкция в виде однострочного блока:
<%pl[(:|=)[name]] [keys] [perl code] %>
3. Многострочный блок:
<%pl[(:|=)[name]] [keys]
[perl code]
%>
где
‘%pl‘, ‘<%pl‘, ‘%>‘ — указатели инструкции (определяют начало и конец кода Perl);
[name] — имя блока (используется при идентификации блоков, преимущественно при параллельном программировании);
‘:‘ или ‘=‘ — разделители (с одной стороны являются разделителями между указателями инструкции и именем блока, с другой стороны, обладают рядом дополнительных функциональных особенностей);
[keys] — управляющие ключи (позволяют видоизменять код Perl, заключенный в инструкции, перед тем как его передать интерпретатору на выполнение);
[perl code] — код Perl.
%pl print sqrt(2); <%pl print $var; %> <%pl= $var; %> <%pl foreach my $key(keys(%ENV)) { print "$key — $ENV{$key}<br>"; } %>
Управляющие элементы [name] и [keys] используются не так часто, и с успехом можно обойтись и без них, но их использование бывает весьма удобным.
<%pl:f1 -fork # Код дочернего процесса my $f = "Данные дочернего процесса f1"; sleep 1; return $f; %> <%pl -join=f1 # Результат дочернего процесса f1 print $phl_join{f1}; %>
К стандартным функциям Perl в PHL дополнительно добавлена функция ‘include()‘), реализованная для возможности сборки документа из нескольких файлов.
%pl include($file_name); <%pl include("$file_name", "socket"); %> <%pl my $result = include("$file_name", "open decode"); %>
Указатели ^
По умолчанию указатели имеют вид: ‘<%pl‘, ‘%>‘ и ‘%pl‘.
Указатели можно переопределить в настройках файла ‘Phl.pm‘ или в конфигурационном файле ‘config.phl‘. В результате, можно написать так <% …code perl… %> или так [ …code perl… ] или даже вoт так ¦ …code perl… ¦.
При желании можно определить свои собственные (дополнительные) указатели инструкций. Это реализуется с помощью специально оформленных модулей.
К примеру, с помощью модуля ‘HTML::Phl::Php‘ в дополнение к указателю инструкции ‘<%pl‘ добавляется указатель ‘<%php‘, позволяющий выполнить простой код языка программирования PHP.
1 %pl -ev use HTML::Phl::Php; 2 3 <%php 4 echo "PHP >> <b>OK</b><br>"; 5 echo date('H:i:s d.m.Y'); 6 %>
14:23:22 26.12.2016
Разделители ^
Задача разделителей — отделить указатель инструкции от имени блока.
В отличие от разделителя ‘:‘, разделитель ‘=‘ изменяет в анализаторе интерпретацию кода. При этом, результат применения разделителя ‘=‘ в однострочном и многострочном блоках различаются.
1 %pl my $test = "<b>тест</b>"; 2 3 1. Переменная '<%pl= $test %>' внутри однострочного блока. 4 <br><br> 5 6 <%pl=name1 7 2. Переменная '$test' внутри 8 многострочного блока '<b>$phl_blok[1]</b>' (разделитель '='). 9 %> 10 <br><br> 11 12 <%pl:name2 13 print "3. Переменная '$test'"; 14 print "внутри многострочного блока '<b>$phl_blok[2]</b>' (разделитель ':')."; 15 %>
1 my $test = "<b>тест</b>"; 2 print <<'[HTML]'; 3 4 [HTML] 5 print <<'[HTML]' =~ /(.*)/; 6 1. Переменная ' 7 [HTML] 8 print($test); 9 print <<'[HTML]'; 10 ' внутри однострочного блока. 11 [HTML] 12 print <<'[HTML]'; 13 <br><br> 14 15 [HTML] 16 print <<"[HTML]"; 17 2. Переменная "$test" внутри 18 многострочного блока "<b>$phl_blok[1]</b>" (разделитель "="). 19 [HTML] 20 print <<'[HTML]'; 21 <br><br> 22 23 [HTML] 24 print "3. Переменная '$test'"; 25 print "внутри многострочного блока '<b>$phl_blok[2]</b>' (разделитель ':').";
2. Переменная ‘тест‘ внутри многострочного блока ‘name1‘ (разделитель ‘=’).
3. Переменная ‘тест‘внутри многострочного блока ‘name2‘ (разделитель ‘:’).
Ключи ^
Ключи позволяют видоизменять код perl, размещенный в инструкциях. Их можно указывать в полном или в сокращенном виде:
-begin
-end
-perl_all
-eval
-fork
-thread
-join
• Ключи ‘-begin‘ [ ‘-bg‘ ] и ‘-end‘
При использовании ключа ‘-begin‘ анализатор берет код perl, содержащийся в инструкции, и оборачивает его блоком ‘BEGIN {}‘.
То же самое происходит при использовании ключа ‘-end‘ — код perl помещается в блок ‘END {}‘.
Исходный код:
1 1. Текст HTML<br> 2 <%pl -end 3 print "2. Первый end<br>"; 4 %> 5 3. Текст HTML<br> 6 7 <%pl -begin 8 print "4. Первый begin<br>"; 9 %> 10 5. Текст HTML<br> 11 12 <%pl -end 13 print "6. Второй end<br>"; 14 %> 15 7. Текст HTML<br> 16 17 <%pl -bg 18 print "8. Второй begin<br>"; 19 %> 20 9. Текст HTML<br>
8. Второй begin
1. Текст HTML
3. Текст HTML
5. Текст HTML
7. Текст HTML
9. Текст HTML
6. Второй end
2. Первый end
• Ключ ‘-perl_all‘ [ ‘-pl‘ ]
При использовании данного ключа, отпадает необходимость ограничивать код perl указателями инструкций. Анализатор будет воспринимать весь текст документа, как Perl-код.
1 %pl -pl 2 3 use CGI; 4 5 print "Content-type: text/html; charset=utf-8\n\n"; 6 7 my $test = "Текст"; 8 my $q = new CGI; 9 10 print $q -> h4("$test из модуля CGI"); 11 print ("<H4>$test из Phl</H4>");
Текст из модуля CGI
Текст из Phl
• Ключ ‘-eval‘ [ ‘-ev‘ ]
Ключ позволяет выполнить код, заключенный внутри инструкции, в процессе работы анализатора (перед его выполнением eval).
Например, попробуем с помощью данного ключа изменить указатели ‘<%pl‘ и др., разместив в коде следующую инструкцию:
1 <%pl -eval 2 $phl{lt} = '['; 3 $phl{rt} = ']'; 4 $phl{ln} = '~'; 5 $phl{sh} = ''; 6 %>
Указатели инструкций приобрели совершенно другой вид. Теперь инструкцию можно написать таким вот образом:
1 [= 2 Многострочный блок 3 ]
или таким
1 [ print "Однострочный блок" ]
или таким
1 ~ print "Линейная инструкция"
• Ключ ‘-fork‘ [ ‘-fk‘ ]
Код, заключенный внутри инструкции, выполняется в параллельном дочернем процессе, созданном в результате запуска fork().
1 <%pl:f1 -fork 2 # Код дочернего процесса с именем f1 3 my $f; 4 sleep 1; # Параллельная обработка данных процессом f1 5 return $f; 6 %>
• Ключ ‘-thread‘ [ ‘-td‘ ]
Код, заключенный внутри инструкции, выполняется в параллельном потоке («нити», «ветке» процесса), созданном стандартным модулем ‘threads‘ в рамках одного процесса.
1 <%pl:t1 -thread 2 # Код нити с именем t1 3 my $t; 4 sleep 1; # Параллельная обработка данных нитью t1 5 return $t; 6 %>
• Ключ ‘-join‘ [ ‘-jn‘ ]
Ключ дает возможность получить результаты выполнения дочерних процессов и нитей.
Результаты размещаются в хэше %phl_join, ключами которого являются имена создаваемых процессов/потоков. Если при обращении за результатом нужные параллельные процессы ещё не завершились, программа ждет их завершения.
1 <%pl -join 2 # Результаты выполнения параллельных дочерних процессов и потоков 3 foreach my $key(keys(%phl_join)) { 4 if (ref $phl_join{$key}) { # если значение - ссылка 5 my @result = @{$phl_join{$key}}; 6 print "процесс '$key' - результат первого аргумента '$result[0]'"; 7 } else { 8 print "процесс '$key' - результат '$phl_join{$key}'"; 9 } 10 } 11 %>
• Дополнительные ключи
При желании можно определить свои собственные (дополнительные) ключи или переопределить существующие. Это реализуется с помощью специально оформленных модулей.
Так, к примеру, с помощью модуля ‘HTML::Phl::Utilit‘ и ключа ‘-import‘ [ ‘-im‘ ] можно просмотреть список всех указателей, ключей и параметров, в данный момент доступных программе.
1 %pl -ev use HTML::Phl::Utilit; 2 3 %pl -import
• param:
— php
• sh:
— php
2. HTML::Phl::Psimple
• param:
— Simple
— sl
3. HTML::Phl::Result
• param:
— result
4. HTML::Phl::Ru
• sh:
— рус
5. HTML::Phl::Utilit
• eval:
— analys
— as
— listing
— lt
• include:
— CONFIG
— TIMER
• key:
— analys
— as
— cf
— config
— im
— import
— listing
— lt
— no_timer
— nt
— timer
— tm
• param:
— listing
— lt
Функции ^
В PHL добавлена всего одна функция ‘include()‘, реализованная для возможности сборки документа из нескольких файлов, содержащих HTML (TXT) или PHL разметку.
Функция ‘include()‘ похожа на стандартную Perl функцию ‘open()‘, с тем отличием, что первым аргументом является имя включаемого в документ файла, а вторым — один или несколько специальных управляющих параметров.
1 %pl include($file_name); 2 3 <%pl include("$file_name", "socket"); %> 4 5 <%pl 6 my $result = include($file_name, "open decode"); 7 %>
В общем случае, написание функции ‘include()‘ выглядит так:
include("file_name" [, "param" [, "name_process"]]);
file_name:
«file_name.phl»
«file_name.cgi»
«file_path/file_name.phl»
"/file_path/file_name.html"
«httр://domain/file_path/file_name.html»
[param]:
phl, exist, head
abs, no_abs, no_eval
no_strict, open, decode
no_decode, cgi, socket
fork, thread
дополнительные параметры и зависимости:
phl [.phl] <= exist, head, abs, decode
cgi [.cgi] <= require, decode
open <= decode, abs
socket <= exist, head, no_abs, decode, no_decode
fork <= waitpid, no_waitpid
thread <= join, detach
Первый аргумент ‘file_name‘ кроме имени файла может содержать зарезервированные слова "JOIN", "CONFIG" или "TIMER".
Если файл ‘file_name‘ имеет расширение ‘.phl‘, то такой файл идентифицируется, как файл формата PHL. Расширение может быть изменено в настройках с помощью $phl{pl}.
При вызове функции ‘include()‘ в неопределенном контексте результат выполнения кода Perl помещается в тело документа внутри функции print(). При скалярном или списковом контексте результат возвращается в виде запрашиваемого значения переменной или списка значений соответственно.
1 <%pl 2 include("file_name.phl"); 3 my $result = include("file_name.phl"); 4 my @result = include("file_name.phl"); 5 %>
Второй аргумент функции ‘include()‘ может содержать один или несколько специальных управляющих параметров.
• Параметр ‘phl‘
Данный параметр указывает обработчику, что код, содержащийся в подключаемом файле, представляет собой документ формата PHL.
Данные файла отправляются в анализатор, где преобразуются в perl-код и передаются ‘eval‘.
Параметр ‘phl‘ выполняет аналогичные действия, если бы мы в имени включаемого файла просто указали расширение ‘.phl‘ (расширение можно изменить в настройках в ‘$phl{pl}‘).
1 <%pl 2 include("file_name.txt", "phl"); 3 my $result = include("file_name.html", "phl decode=utf-8"); 4 my @result = include("file_name", "phl abs"); 5 %>
• Параметр ‘exist‘ (‘ex‘)
Позволяет проверить существование файла.
1 <%pl 2 my $exist_file = include("$file_name", "exist"); 3 if ($exist_file) { 4 print "Файл $file_name найден"; 5 } else { 6 print "Файл $file_name не найден"; 7 } 8 %>
• Параметр ‘head‘ (‘hd‘)
Возвращает список из 5 элементов: Content type, Document length, Modified time, Expires, Server.
1 <%pl 2 my @head = include("$file_name", "head"); 3 %>
• Параметр ‘abs‘
Если присутствует параметр ‘abs‘, осуществляется преобразование относительных ссылок, указанных в файле, в абсолютные.
%pl include("$file_name", "abs");
• Параметр ‘no_eval‘ (‘ne‘)
При указании данного параметра результат выполнения кода включаемого файла игнорируется.
<%pl include("$file_name", "no_eval") %>
• Параметр ‘no_strict‘ (‘ns‘)
Если указан параметр ‘no_strict‘, то на код загружаемого файла ‘$file_name‘ действие прагмы ‘use strict‘ не распространяется.
1 <%pl 2 include("$file_name", "ns"); 3 %>
• Параметр ‘open‘ ( ‘on‘ )
Как и функция ‘open()‘, служит для открытия файла и извлечения из него каких-либо данных (возможность записи данных в файл отсутствует).
1 <%pl 2 include("$file_name", "open"); 3 my $result = include("$file_name", "open decode=koi8-r"); 4 my @result = include("$file_name", "on, decode=cp1251, abs"); 5 %>
• Параметр ‘decode‘ (‘dc‘)
При наличии параметра ‘decode‘ данные из указанной в параметрах кодировки (к примеру, ‘decode=cp1251‘) декодируются во внутренний формат Perl.
Если кодировка не указана или отсутствует параметр ‘decode‘, то при декодировании подразумевается, что кодировка включаемого файла соответствует $phl{encoding_in}, указанной в настройках phl.pm (или config.phl).
Если кодировка результирующего документа отлична от ‘utf-8‘, то дополнительно осуществляется кодирование данных в кодировку $phl{encoding_out}, указанную в настройках phl.pm (или config.phl).
Кодирование и декодирование данных осуществляется с использованием стандартного модуля ‘Encode.pm‘.
• Параметр ‘cgi‘
Данный параметр предназначен для подключения cgi-скриптов, написанных на Perl.
1 <%pl 2 include("file_name.cgi"); 3 include("$file_name", "cgi"); 4 include("$file_name", "cgi require"); 5 include("file_name.cgi", "decode=cp866"); 6 %>
• Параметр ‘socket‘ (‘sk‘)
Применяется для загрузки web-документа с помощью стандартного модуля ‘IO::Socket::INET‘
1 <%pl 2 include("file_name.html", "socket"); 3 include("http://domain/"); 4 my $text = include("http://domain/file_path/file_name.html", "decode=cp1251"); 5 my @result = include("$file_name", "decode no_abs"); 6 %>
Если адрес включаемого в документ файла начинается с http или ftp, то указывать параметр ‘socket‘ не обязательно.
Совместно с параметром ‘socket‘ могут применяться дополнительные параметры ‘exist‘, ‘head‘, ‘no_abs‘, ‘decode‘, ‘no_decode‘.
- дополнительный параметр ‘exist‘ (‘ex‘)
Позволяет проверить существование домена, файла, адреса.
1 <%pl 2 my @include_name_file = ( 3 'dir1/name_file.html', 4 '/dir2/name_file.php', 5 'http://www.yandex.ru', 6 'http://www.yandex/eklmnfjoeqxngsitwf.html', 7 'http://eklmnfjoeqxngsitwfhoevd.ru' 8 ); 9 10 foreach my $name_file (@include_name_file) { 11 my $ex = include("$name_file", "socket exist"); 12 if ($ex) { 13 print "Файл '$name_file' найден<br>"; 14 } elsif (!defined $ex) { 15 print "Ресурс '$name_file' не отвечает<br>"; 16 } else { 17 print "Файл '$name_file' не найден<br>"; 18 } 19 } 20 %>
- дополнительный параметр ‘head‘ (‘hd‘)
Возвращает заголовок документа
1 <%pl 2 foreach my $name_file (@test_name_file) { 3 my head = include("$name_file", "socket head"); 4 if ($#head) { 5 print "Заголовок от '$name_file' получен => '@head[0..3]'<br>"; 6 } else { 7 print "Заголовка от '$name_file' нет => '@head'<br>"; 8 } 9 } 10 %>
- дополнительный параметр ‘no_abs‘ (‘na‘)
По умолчанию, все относительные ссылки заменяются на абсолютные, но если указан параметр ‘no_abs‘, то этого не происходит.
%pl include("$file_name", "socket no_abs");
- дополнительный параметр ‘decode‘ (‘dc‘)
Служит для декодирования документов из кодировки, указанной параметром ‘decode‘, во внутренний формат Perl и далее в кодировку, указанную в настройках в $phl{encoding_out}.
Если параметр ‘decode‘ используется без указания исходной кодировки запрашиваемого файла, то декодирование осуществляется с учетом кодировки, указанной в заголовке файла в ‘charset‘ (при наличии).
Если параметр ‘decode‘ не используется, по умолчанию подразумевается, что наш файл в кодировке utf-8.
При использовании параметра ‘no_decode‘ (‘nd‘) никакого декодирования данных не происходит.
1 <%pl 2 include("http://www.rbc.ru", "decode=utf-8"); 3 include("http://www.mail.ru", "decode"); 4 my $html_text1 = include("http://ru.motorsport.com"); 5 my $html_text2 = include("http://www.google.com", "nd"); 6 %>
• Параметр ‘fork‘ (‘fk‘)
Код загружаемого файла выполняется в параллельном дочернем процессе, созданном в результате запуска ‘fork()‘.
1 <%pl 2 include("$file_name", "fork"); 3 %>
Результат выполнения параллельного процесса можно вернуть в родительский, используя ‘return‘ в тексте инструкции включаемого файла.
1 <%pl 2 <font color=#646464><I># Код дочернего процесса $phl_var{name}</I></font> 3 my $f = "Передаваемые данные"; 4 sleep 1; 5 return $f; 6 %>
В третьем аргументе функции ‘include()‘ можно указать уникальное имя дочернего процесса, чтобы затем обратиться за результатом выполнения дочернего процесса «по имени».
1 <%pl 2 include("$file_name", "fork", "f1"); 3 %>
- дополнительный параметр ‘waitpid‘ (‘wd‘)
Для того, чтобы вернуть результат выполнения дочернего процесса в точку вызова функции ‘include()‘, необходимо дополнительно к параметру ‘fork‘ указать параметр ‘waitpid‘ или в качестве третьего аргумента функции ‘include()‘ указать ‘waitpid‘.
Результат отработки параллельного процесса можно вернуть обратно в родительский процесс, вызвав ‘include()‘ в скалярном или списковом контексте.
1 <%pl 2 $result = include("$file_name", "fork waitpid"); 3 @result = include("$file_name", "fork", "waitpid"); 4 %>
На самом деле, можно вообще отказаться от параметра ‘waitpid‘, как во втором так и в третьем аргументе. В таком случае, программа всё равно будет ждать завершения дочернего процесса, а функция ‘include()‘ получается менее громоздкой.
1 <%pl 2 @result = include("$file_name", "fork", ""); 3 $result = include("$file_name", "fk"); 4 %>
- дополнительный параметр ‘no_waitpid‘ (‘nw‘)
Результат выполнения процесса вернуть не удастся, если только, не попробовать что-либо записать в файл или вывести на экран.
1 <%pl 2 include("$file_name", "fork no_waitpid"); 3 include("$file_name", "fork", "no_waitpid"); 4 %>
- аргумент ‘JOIN‘
Для обращения за результатом выполнения дочернего процесса можно использовать функцию ‘include()‘, где в качестве первого аргумента необходимо указать зарезервированное слово ‘JOIN‘, вторым аргументом — имя или имена дочерних процессов.
1 <%pl 2 include("$file_name", "fork", "f1"); 3 4 # Далее может следовать тело программы с некоторым кодом 5 6 my $rezult = include("JOIN", "f1"); 7 %>
Вернуть результаты нескольких или даже всех параллельных процессов можно обратившись к хэшу, ключами которого будут имена процессов, значениями — результаты их выполнения.
1 <%pl 2 my %join_2_3 = include("JOIN", "f2 f3"); 3 print "Результат процесса 'f2' = $join_2_3{f2}<br>"; 4 5 my %join_all = include("JOIN"); 6 foreach my $key(keys(%join_all)) { 7 if (ref $join_all{$key}) { 8 my @result = @{$join_all{$key}}; 9 print "Результат процесса '$key' = '$join_all{$key}' => "; 10 print "и первый разыменованный элемент массива = '$result[0]'<br>"; 11 } else { 12 print "Результат процесса '$key' = '$join_all{$key}'<br>"; 13 } 14 } 15 %>
• Параметр ‘thread‘ (‘td‘)
Создается, так называемая, «нить» («поток») — своеобразная ветка процесса, в которой возможно выполнение кода параллельно коду породившего нить процесса.
Для создания нити используется стандартный модуль ‘thread‘ (в свою очередь, Perl должен быть настроен на работу с тредами).
1 <%pl 2 include("$file_name", "thread"); 3 %>
Как и в случае с параметром ‘fork‘, при использовании нитей существует возможность вернуть результат выполнения созданной нити, как в точку вызова функции ‘include()‘, так и в произвольную точку программы или вообще «забыть» о результате, ничего не возвращая.
- дополнительный параметр ‘join‘ (‘jn‘)
Результат выполнения нити возвращается в точку вызова, при этом родительский процесс временно прекращает своё выполнение и ждет получения данных (от созданных потоков).
1 <%pl 2 $result = include("$file_name", "thread join"); 3 @result = include("$file_name", "thread", "join"); 4 %result = include("$file_name", "thread"); 5 %>
- дополнительный параметр ‘detach‘ (‘dh‘)
Нить создается, но что в ней происходит основная ветка процесса не знает.
1 <%pl 2 include("$file_name", "thread detach"); 3 include("$file_name", "thread", "detach"); 4 %>
Вернуть данные в любую точку основной ветки процесса можно, присвоив нити имя (по аналогии с дочерним процессом, создаваемым параметром ‘fork‘).
1 <%pl 2 include("$file_name", "thread", "t1"); 3 include("$file_name", "thread", "t2"); 4 include("$file_name", "thread", "t3"); 5 6 my $rezult = include("JOIN", "t2"); 7 print "Результат нити 't2' = '$rezult'<br>"; 8 9 my %join = include("JOIN", "t1 t3"); 10 print "Результат нити 't1' = '$join{t1}'<br>"; 11 print "Результат нити 't3' = '$join{t3}'<br>"; 12 %>
• Собственные параметры
При желании можно определить свои собственные (дополнительные) параметры или переопределить существующие. Это реализуется с помощью специально оформленных модулей.
Так, к примеру, с помощью модуля ‘HTML::Phl::Utilit‘ и параметра ‘analys‘ (‘as‘) появляется возможность просмотреть сформированный анализатором код perl включаемого файла перед его выполнением eval.
пример:
1 %pl -ev use HTML::Phl::Utilit; 2 3 <%pl 4 include("$file_name", "as"); 5 %>
1 Текст HTML<br> 2 3 <%pl 4 my $test = "Текст Perl<br>"; 5 print ("$test"); 6 %> 7 8 Текст HTML<br>
1 print <<'[HTML]'; 2 Текст HTML<br> 3 4 [HTML] 5 my $test = "Текст Perl<br>"; 6 print ("$test"); 7 print <<'[HTML]'; 8 9 Текст HTML<br> 10 [HTML]
Модули-расширения PHL ^
Для достижения большей гибкости работы в PHL реализована возможность задавать собственные указатели инструкции [sh], ключи [keys], первый аргумент [include] и параметры [param] функции ‘include()‘.
<%[sh] [keys]
…
include("[include]", "[param]");
…
%>
Новые ключи, параметры и указатели импортируются в phl.pm из специально написанных для данных целей модулей.
Для примера в PHL включены 4 модуля:
use HTML::Phl::Utilit; use HTML::Phl::Psimple; use HTML::Phl::Php; use HTML::Phl::Ru;
Модули можно подключить как в файле ‘phl.pm‘ или ‘config.phl‘, так и в файле PHL.
1 %pl -ev use HTML::Phl::Utilit 2 3 <%pl 4 # код perl 5 %>
• Модуль ‘HTML::Phl::Utilit‘
Модуль экспортирует в программу 5 ключей, 2 параметра и 2 аргумента для функции ‘include()‘.
[keys]:
-listing
-analys
-config
-timer
-no_timer
[param]:
listing
analys
[include]:
CONFIG
TIMER
Ключи ‘-listing‘ [ ‘-lt‘ ] и ‘-analys‘ [ ‘-as‘ ] и параметры ‘listing‘ ( ‘lt‘ ) и ‘analys‘ ( ‘as‘ ) дают, возможность просмотреть листинг программы или сформированный анализатором код perl перед его выполнением eval.
Ключ ‘-listing‘ [ ‘-lt‘ ]
1 Текст HTML 1 2 <br><br> 3 4 <%pl -lt 5 my $test = "Текст Perl<br>"; 6 print "$test"; 7 %> 8 <br> 9 10 Текст HTML 2
1 my $test = "Текст Perl<br>"; 2 print "$test";
Текст HTML 2
Ключ ‘-analys‘ [ ‘-as‘ ]
1 %pl -as 2 3 <%pl 4 my $test = "Текст Perl<br>"; 5 print ("$test"); 6 %> 7 8 Текст HTML и <%pl= $test %>
1 ; 2 print <<'[HTML]'; 3 4 [HTML] 5 my $test = "Текст Perl<br>"; 6 print ("$test"); 7 print <<'[HTML]'; 8 9 [HTML] 10 print <<'[HTML]' =~ /(.*)/; 11 Текст HTML и 12 [HTML] 13 print($test);
Ключ ‘-config‘ [ ‘-cf‘ ] или аргумент ‘CONFIG‘ функции ‘include()‘ выводят на печать хэш %phl конфигурационных переменных.
1 %pl -config 2 3 или так 4 5 <%pl 6 include("CONFIG"); 7 %>
Конфигурационные переменные
bottom = »
bufer = ‘1‘
config = ‘config.phl‘
config_path = »
encoding_in = ‘utf8‘
encoding_out = ‘utf8‘
finde_config = ‘yes‘
header = ‘Content-type: text/html; charset=utf-8‘
index = ‘index.phl‘
ln = ‘%‘
locale = ‘utf8‘
lt = ‘<%‘
pl = ‘phl‘
rt = ‘%>‘
script_dir = »
sh = ‘pl‘
threads = ‘1‘
timer = ‘0‘
top = »
Ключи ‘-timer‘ [ ‘-tm‘ ] и ‘-no_timer‘ [ ‘-nt‘ ] позволяют изменить механизм вывода на экран временных промежутков работы компонентов программы,
а используя аргумент ‘TIMER‘ функции ‘include()‘ можно задать свой таймер.
1 <%pl 2 # запуск встроенного таймера 3 %pl -timer 4 5 # остановка встроенного таймера 6 %pl -nt 7 %>
timer = 4
2. Проверяем результат на тестовом ‘include()’ (без параметров)
Результат =>
• Время — 0.248574 [0.226931 ] < INCLUDE_BEGINE ()
• Время — 0.248953 [0.227302 ] < INCLUDE_END ()
test: timer = 4
3. Выключаем timer ключем ‘-no_timer’ или ‘-nt’
4. Проверяем результат на тестовом ‘include()’
Результат => test: timer = 0
1 <%pl 2 # пример создания своего таймера 3 include("TIMER", "имя таймера"); 4 %>
• Время — 0.000005 < TIMER (name_timer_1)
ждем некоторое время — sleep 0.2
• Время — 0.200440 < TIMER (name_timer_1)
Новый таймер 2
• Время — 0.000004 < TIMER (name_timer_2)
ждем некоторое время — sleep 0.5
• Время — 0.701001 < TIMER (name_timer_1)
• Время — 0.500496 < TIMER (name_timer_2)
Новый таймер 3
• Время — 0.000003 < TIMER (name_timer_3)
ждем некоторое время — sleep 0.35
• Время — 1.051648 < TIMER (name_timer_1)
• Время — 0.851139 < TIMER (name_timer_2)
• Время — 0.350579 < TIMER (name_timer_3)
• Модуль ‘HTML::Phl::Php‘
Экспортирует указатель ‘php‘, превращая указатель инструкции ‘<%pl‘ в ‘<%php‘, для возможности работы с кодом языка программирования PHP;
1 %pl -ev use HTML::Phl::Php; 2 3 %pl our $pl = 5; 4 5 Исходная переменная PERL: $pl = <b>'<%pl= $pl %>'</b>. 6 <br><br> 7 8 <%php 9 echo "Значение переменной $pl передаем в PHP ($pl -> $php).<br>"; 10 OUT_PERL($pl -> $php); 11 12 echo "<li>Переменная $php = $php.</li><br>"; 13 14 echo "В PHP изменяем значение переменной: $php = 2 * $php + 1.5.<br><br>"; 15 $php = 2 * $php + 1.5; 16 17 echo "Возвращаем значение переменной $php в PERL ($php -> $pl).<br>"; 18 IN_PERL($php -> $pl); 19 %> 20 21 <li>Результирующая переменная PERL: $pl = <b>'<%pl= $pl %>'</b></li>.
Значение переменной $pl передаем в PHP ($pl -> $php).
Переменная $php = 5.
В PHP изменяем значение переменной: $php = 2 * $php + 1.5.
Возвращаем значение переменной $php в PERL ($php -> $pl).
Результирующая переменная PERL: $pl = ‘11.5’.
• Модуль ‘HTML::Phl::Ru‘
Экспортирует указатель ‘рус‘, превращая указатель инструкции ‘<%pl‘ в ‘<%рус‘, позволяя работать с некоторыми функциями и операторами кириллического написания.
1 %pl -ev use HTML::Phl::Ru; 2 3 <%рус 4 my @имена_файлов = ( 5 'file_exist.phl', 6 'http://www.pushkinmuseum.ru', 7 'http://www.pushkinmuseum.ru/467899', 8 'http://eklmn12344556778.ru' 9 ); 10 11 foreach my $имя_файла (@имена_файлов) { 12 my $найдено = ВКЛЮЧИТЬ("$имя_файла", "socket exist"); 13 ЕСЛИ ($найдено) { 14 ПЕЧАТЬ "'$имя_файла' - <B>найден</B><br>"; 15 } ИЛИ ЕСЛИ (!defined $найдено) { 16 ПЕЧАТЬ "'$имя_файла' - <B>не отвечает</B><br>"; 17 } ИНАЧЕ { 18 ПЕЧАТЬ ("'$имя_файла' - <B>не найден</B><br>"); 19 } 20 } 21 %>
‘http://www.pushkinmuseum.ru’ — найден
‘http://www.pushkinmuseum.ru/467899’ — не найден
‘http://eklmn12344556778.ru’ — не отвечает
• Модуль ‘HTML::Phl::Psimple‘
Экспортирует параметр ‘Simple‘ [‘sl‘] для работы со стандартным модулем Perl ‘LWP::Simple‘;
Структура модулей-расширений
Для возможности экспорта ключей, параметров и указателей модули должны размещаться в определенной папке (по умолчанию — в ‘Phl’, находящейся рядом с основным файлом программы ‘phl.pm‘) и содержать двумерный хэш ‘%phl_import‘, в котором ключами второго хеша будут экспортируемые ключи, параметры и указатели.
Хэш ‘%phl_import‘ может включать 5 ключей — ‘sh‘, ‘key‘, ‘param‘, ‘include‘ и ‘eval‘.
1 our %phl_import = ( 2 key => { 3 tm => \&HTML::Phl::Utilit::key_timer, 4 im => \&HTML::Phl::Utilit::print_import, 5 }, 6 include => { 7 TIMER => \&HTML::Phl::Utilit::my_timer, 8 CONFIG => \&HTML::Phl::Utilit::config, 9 }, 10 param => {lt => \&HTML::Phl::Utilit::open_listing}, 11 sh => {'рус' => \&HTML::Phl::Ru::ru_perl}, 12 eval => {as => \&HTML::Phl::Utilit::eval_code} 13 );
Конфигурационные настройки ^
Конфигурационные файлы ‘config.phl‘ позволяют переопределять базовые переменные, указанные в ‘phl.pm‘. Их можно размещать в любой web-директории, содержащей PHL файлы.
Конфигурационные файлы разрабатываются в формате Perl и содержат значения ключей хеша %phl.
$phl{pl} = ‘phl‘;
# Имя файла, которое ищет функция ‘include()’ в директории, если не указан загружаемый файл, к примеру domain.ru/file_path
$phl{index} = ‘index.phl‘;
# Осуществлять или не осуществлять поиск конфигурационных файлов ‘config.phl’ в директории загружаемых include() файлов [ yes/no ]
$phl{finde_config} = "yes";
# Определение указателей инструкций [ по умолчанию, ‘<%pl code_perl %>’, ‘%pl line_code_perl’ ]
$phl{lt} = ‘<%‘;
# начало блока инструкции
$phl{rt} = ‘%>‘;
# конец блока инструкции
$phl{ln} = ‘%‘;
# линейная инструкция
$phl{sh} = ‘pl‘;
# указатель принадлежности к языковой конструкции (в данном случае к perl)
# Заголовок документа [ к примеру, «Content-type: text/html; charset=utf-8\n\n»; $phl_header = "" — нет заголовка ]
$phl{header} = "";
# Верхний колонтитул
$phl{top} = "";
# Нижний колонтитул
$phl{bottom} = "";
# Сброс буфера [ «1» соответствует => $| = 1, «0» соответствует => $| = 0 ]
$phl{bufer} = 1;
# Использование потоков (нитей) [ 1/0 ]
$phl{threads} = 1;
# Подсчитывается время загрузки компонентов [ различная степень детализации => «0» — нет, «1»…«4» — да ]
$phl{timer} = 0;
# Кодировка файлов [ cp1251, utf8, koi8-r, iso-8859-5, cp866… ]
$phl{encoding_in} = "utf8"; # кодировка загружаемых include() файлов
$phl{encoding_out} = "utf8"; # кодировка результирующего документа
$phl{locale} = "utf8"; # кодировка имен файлов файловой системы
Дистрибутив PHL ^
Модуль ‘HTML::Phl’ вместе с дополнительными модулями-расширениями, тестами и примерами можно скачать здесь.
При желании опробовать работу модуля в ОС Android, необходимо установить SL4A, позволяющий запускать в данной среде perl-программы, в частности веб-сервер, способный генерировать HTML страницы по запросам Perl. Как написать свой веб-сервер на Perl под Android можно ознакомиться здесь или скачать немного измененный под работу с PHL вариант здесь.
ссылка на оригинал статьи https://habrahabr.ru/post/304634/
Добавить комментарий