
В статье приведена спецификация модуля 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 вариант здесь.
Комментарии (7)
Alexeyco
27.12.2016 09:56Мама, а зачем дяди заново изобретают PHP?
Pyu
27.12.2016 11:56Я бы задал вопрос иначе — «зачем использовать Perl, там где уже давно применяется PHP»?
Perl, конечно чем-то похож на PHP, но всё-таки это совсем другой язык программирования, и использовать PHP для веб-разработки совсем не обязательно, если задуманное можно написать на Perl.
Но для удобства, в данном случае, конечно были применены механизмы вставки кода Perl в html-документ, похожие на те, что в своё время были использованы разработчиками PHP. Это, наверное, и вводит в заблуждение, относительно изобретения PHP.
kloppspb
По ссылке на установку SL4A весь абзац, начинающийся со слов «Устанавливается SL4A следующим образом», уже давно не актуален.
Pyu
Изменил ссылку на актуальную.
Если кому то будет интересно, напишу поподробнее, что со всем этим можно делать на Android (как в той самой статье, которая стала уже не актуальна).