--- parser3/operators.ru.txt 2002/03/18 15:29:45 1.20 +++ parser3/operators.ru.txt 2002/05/15 08:58:00 1.37 @@ -15,7 +15,7 @@ Xне сделано, видимо, не будет сделано пустая таблица не defined пустой hash не defined !eq ne lt gt le ge для сравнения строк, - !in "/dir/" для проверки[раньше ^start] + !in "/dir/" для проверки ["внутри не допустимы, если надо сравнить со сложным, пусть это будет переменная]. !is 'type' для проверки типа левого операнда, @@ -51,30 +51,29 @@ Xне сделано, видимо, не будет сделано !^for[i](0;4){тело}[[разделитель]|{разделитель который выполняется перед непустым очередным не первым телом}] !^use[модуль] !^try{ - ... + ... !^throw[sql.connect;вася;болван] // был ^error[текст] ... }{ - ^if($exception.type eq sql){ - $exception.handled(1) ^rem{флаг, что exception обработан} - .... - } - - ^switch($exception.type){ - ^case[sql;mail]{ - $exception.handled(1) - код, обрабатывающий sql ошибку - $exception.type = sql.connect - $exception.file $exception.lineno [если не запрещены при компиляции] - $exception.source = вася - $exception.comment = болван - ^if($exception.type eq connect){^cache[read]} - } - ^case[_default]{ - код, обрабатывающий другую ошибку - ^throw[$exception] << re-throw - } - } + ^if($exception.type eq sql){ + $exception.handled(1) ^rem{флаг, что exception обработан} + .... + } + + ^switch($exception.type){ + ^case[sql;mail]{ + $exception.handled(1) + код, обрабатывающий sql ошибку + $exception.type = sql.connect + $exception.file $exception.lineno [если не запрещены при компиляции] + $exception.source = вася + $exception.comment = болван + } + ^case[_default]{ + код, обрабатывающий другую ошибку + ^throw[$exception] << re-throw + } + } } ^exit[] + - прекращяет обработку запроса. удобно сделать после выставления 401 ошибки @@ -86,7 +85,7 @@ Xне сделано, видимо, не будет сделано default as-is !^taint[[lang]][код] default "just tainted, language unknown" - !^process[строка, которая будет process-ed, как код] + !^process{строка, которая будет process-ed, как код} !^connect[protocol://строка соединения]]{код с ^sql[...]-ями} !mysql://user:pass@{host[:port]|[/unix/socket]}/database? charset=cp1251_koi8& @@ -94,9 +93,11 @@ Xне сделано, видимо, не будет сделано compress=1& named_pipe=1 - !pgsql://user:pass@{host[:port]|[local]}/database + !pgsql://user:pass@{host[:port]|[local]}/database? + client_encoding=win,[to-find-out]& + datestyle=ISO,SQL,Postgres,European,NonEuropean=US,German,DEFAULT=ISO - oracle://user:pass@service? + !oracle://user:pass@service? NLS_LANG=RUSSIAN_AMERICA.CL8MSWIN1251& NLS_LANGUAGE language-dependent conventions NLS_TERRITORY territory-dependent conventions @@ -140,14 +141,24 @@ odbc c:\drives\y\parser3project\odbc\ /**имя_поля**/'literal' !^rem{} !^cache[файл](секунд){код} + !относительное задание времени !скэшировать строку, которая получается при выполнении кода на 'секунд' секунд !если 0секунд, значит не кэшировать, а старый такой стереть - ^cache[delete] << не кэшировать, старое забыть - ^cache[read] << взять скэшированное насильно, игнорируя expires + !^cache[файл][expires date]{код} + !абсолютное задание времени + X^cache[файл] удалить файл [не ругает, если его нет] // такое было, больше не будет, делать ^cache(0) + !^cache(секунд) + !^cache[expires date] + !сигнализирует вышестоящему ^cache "уменьши до стольких-то 'секунд'/'expires'" + !в пределе: ^cache(0) отменить кэширование + X^cache[read] + сигнализирует вышестоящему ^cache "взять скэшированное насильно, игнорируя expires",
+ выдаёт bool "получилось/нет" Xесть глобальный флажок в свойствах/командной строке "не оптимизировать" - !и есть исключение: ^untaint[html]{код} не оптимизируется безотностительно флажка + !и есть исключение: ^untaint[html]{код} не оптимизируется + Xбезотностительно флажка !у всех макросов есть локальная переменная $result, если в неё что положить, !то _это_ будет результатом макроса, а не его тело @@ -220,7 +231,7 @@ odbc c:\drives\y\parser3project\odbc\ !^имя.div(на сколько /) !^имя.mod(на сколько %) !^имя.format[формат] - !^int/double:sql{query}[[$.limit(2) $.offset(4) $.default(0)]] + !^int/double:sql{query}[[$.limit(2) $.offset(4) $.default{0}]] запрос, результат которого должен быть один столбец/одна строка !string @@ -232,7 +243,7 @@ odbc c:\drives\y\parser3project\odbc\ пример: ^if(def $form:name) не пуста? ^if($user.isAlive) истина? [автопреобразование к числу, не ноль?] - !^string::sql{query}[[$.limit(2) $.offset(4) $.default[n/a]]] + !^string::sql{query}[[$.limit(2) $.offset(4) $.default{n/a}]] результат запроса должен быть один столбец/одна строка !^имя.int[] .int(default) целочисленное значение строки. если ломается преобразование, берётся default @@ -240,15 +251,15 @@ odbc c:\drives\y\parser3project\odbc\ если ломается преобразование, берётся default !^имя.format[формат] %d %.2f %02d... !^строка.match[шаблон][[опции поиска]] $prematch $match $postmatch $1 $2... - опции поиска= - i CASELESS - x whitespace in regex ignored - s singleline = $ считается концом всего текста - m multiline = $ считается концом строки[\n], не концом всего текста - g найти все вхождения, а не одно + опции поиска= + i CASELESS + x whitespace in regex ignored + s singleline = $ считается концом всего текста + m multiline = $ считается концом строки[\n], не концом всего текста + g найти все вхождения, а не одно !^строка.match[шаблон][опции поиска]{замена} - опции поиска+= - g заменить все вхождения, а не одно + опции поиска+= + g заменить все вхождения, а не одно !^строка.{l|r}split[разделитель] таблица из столбца $piece !^строка.upper|lower[] X^строка.truncate(предел терпенья) стиль :( @@ -268,7 +279,7 @@ odbc c:\drives\y\parser3project\odbc\ числовое значение равно count[] !^table::create[[nameless]]{данные} старое имя "set" !^table::create[table] - клонирует таблицу + клонирует таблицу !^table::load[[nameless;]путь] !если не nameless, названия колонок берутся из первой строки !пустые строки, и строки в первой колонке содержащие '#', игнорируются @@ -298,6 +309,10 @@ odbc c:\drives\y\parser3project\odbc\ значением $hash.ключ будет hash в котором поля значений будут ключами поля значений могут быть не указаны, тогда ими будут все столбцы, включая ключевой !^таблица.columns[]+ таблица из одного столбца $column + !$отобранное[^таблица.select(выражение)] = таблица из тех же столбцов и строк, у которых условие совпало + $adults[^man.select($man.age>=18)] + + !hash !в выражении @@ -312,7 +327,9 @@ odbc c:\drives\y\parser3project\odbc\ перезаписывает одноимённые !^hash.sub[вычитаемое] !^a.union[b] = объединение + одноимённые остаются !^a.intersection[b] = пересечение + значения a !^a.intersects[b] = bool !^hash::sql{запрос}[[$.limit(2) $.offset(4)]] получается hash(ключи=значения первая колонка ответа) @@ -446,13 +463,13 @@ Xhashfile ] !для отправки под unix используется программа с параметрами, задаваемая - $MAIL.sendmail[команда] - если не будет задана, проверяется, доступна ли - /usr/sbin/sendmail или + $MAIL.sendmail[команда] + если не будет задана, проверяется, доступна ли + /usr/sbin/sendmail или /usr/lib/sendmail - и, если доступна, то запускается с параметром "-t". + и, если доступна, то запускается с параметром "-t". под win32 используется SMTP протокол, сервер задаётся - $MAIL.SMTP[smtp.domain.ru] + $MAIL.SMTP[smtp.domain.ru] !image !$картинка[^image::measure[DATA]] @@ -515,10 +532,11 @@ Xhashfile каталоги для dest создаются с правами 775 каталог старого файла стирается, если после move он остаётся пуст !^file:lock[имя файла]{код} - файл при необходимости создаётся - блокируется - выполняется код - разблокируется + файл при необходимости создаётся + блокируется + выполняется код + разблокируется + Xchmod[...] НЕТ И НЕ БУДЕТ, ЧТОБЫ НЕ МОГЛИ СДЕЛАТЬ executable и запустить, даже если ftp запрещает chmod. !math !$math:PI @@ -533,20 +551,23 @@ Xhashfile !date !время типа time можно использовать в выражениях, подставляет - количество дней с epoch [1 января 1970 (UTC)], дробное + количество дней с epoch [1 января 1970 (UTC)], дробное !всё происходит в localtime, !временная зона задаётся вне parser средствами OS !^date::now[] + !^date::now(смещение в днях) выдаёт сейчас+смещение !^date::create(дней с epoch) // старое имя set - !^date::create(year;month;day[;hour[;minute[;second]]]) // старое имя set + !^date::create(year;month[;day[;hour[;minute[;second]]]]) // старое имя set + !^date::create[дата в формате %Y[-%m[-%d[ %H[:%M[:%S]]]]]] + для удобного создания по значению из базы !$date.year month day hour minute second weekday read-only - !^date.roll[year|month|day](+/- 1) сдвигает дату + !^date.roll[year|month|day](+-смещение) сдвигает дату !^date.sql-string[] %Y-%m-%d %H:%M:%S where published='$дата.sql-string[]' !^date:calendar[rus|eng;год;месяц] выдаёт неименованную таблицу - столбцы: 0..6 + столбцы: 0..6 !^date:calendar[rus|eng;год;месяц;день] выдаёт именнованную таблицу - столбцы: year, month, day, weekday + столбцы: year, month, day, weekday xdoc(xnode) DOM1 attributes: @@ -595,12 +616,13 @@ xdoc(xnode) !cdata-section-elements = qnames !indent = "yes" | "no" !media-type = string /> + !параметры передаются как есть, не xpath выражения !.string[output options] !.save[file.xml;output options] с шапкой !.file[output options] = file output options идентичны атрибутам xsl:output - [исключение: игнорируется cdata-section-elements, нужно будет, сделаю] + [исключение: игнорируется cdata-section-elements, нужно будет, сделаю] выдаёт media-type при подстановке $response:body[сюда] @@ -676,7 +698,7 @@ xdoc(xnode) !XPath: !^node.select[xpath/query/expression] = array of nodes, - empty array if nothing found + empty array if nothing found !^node.selectSingle[xpath/query/expression] = first node if any !^node.selectBool[xpath/query/expression] = bool if any !^node.selectNumber[xpath/query/expression] = double if any @@ -748,21 +770,24 @@ xdoc(xnode) file !$status:rusage hash - !utime user time used - !stime system time used - !maxrss max resident set size - !ixrss integral shared text memory size - !idrss integral unshared data size - !isrss integral unshared stack size + !utime user time used + !stime system time used + !maxrss max resident set size + !ixrss integral shared text memory size + !idrss integral unshared data size + !isrss integral unshared stack size + +!DATA::=string | file !MAIN это класс, загружаемый на автомате из parser3.conf, кучи auto.p и запрашиваемого документа: !parser3.conf cgi: - 1.0) полный путь из переменной окружения PARSER_ROOT_CONFIG - 1.1) configure sysconfdir|windows directory - 2)рядом с бинарником parser'а + 1. или полный путь из переменной окружения HTTP_PARSER_ROOT_CONFIG + или configure sysconfdir|windows directory + 2. или полный путь из переменной окружения HTTP_PARSER_SITE_CONFIG + или рядом с бинарником parser'а isapi: windows directory apache module: 1) ParserRootConfig [httpd.conf only] @@ -775,7 +800,7 @@ xdoc(xnode) !результат которого передаётся в его @post-process[data] if($data is string) ... !результат которого отдаётся пользователю - !если встречается ошибка и try не задан, её можно красиво сообщить пользователю, +!если встречается ошибка и try не задан, её можно красиво сообщить пользователю, !определив !@unhandled_exception[exception;stack] !$exception.type строка "тип проблемы" @@ -786,11 +811,23 @@ xdoc(xnode) там лежат в обратном порядке имена[name] и места вызовов[file line] операторов/методов, приведших к ошибке. - !нужно выключить русский apache: CharsetDisable on +!системные типы ошибок: + !parser.compile ^test[} компиляция (непарная скобка, ...) + !parser.runtime ^if(0). параметры (больше/меньше, чем нужно, не тех типов, ...) + !number.zerodivision ^eval(1/0) ^eval(1%0) + !number.format ^eval(abc*5) + !date.format ^date::create(2002-99-05) + !file.missing ^file:delete[delme] not found + !file.access ^table::load[.] no rights + !image.format ^image::measure[index.html] not gif/jpg + !sql.connect ^connect[mysql://baduser:pass@host/db]{} not found/timeout + !sql.execute ^void:sql{select bad} syntax error + !xml ^xdoc::create{} any error in xml/xslt libs + !smtp.connect not found/timeout + !smtp.execute communication error -!DATA::=string | file +!нужно выключить русский apache: CharsetDisable on ---- - если в MAIN будет определён флаг $ORIGINS(1) то вместо обычного вывода страницы будет +!если в MAIN будет определён флаг $ORIGINS(1) то вместо обычного вывода страницы будет выдан список фрагментов результата с указанием их происхождения