( socket -- n ior )
сколько байт можно сейчас прочесть из сокета
можно использовать перед ReadSocket для того чтобы
избежать блокирования при n=0
( IP -- addr u )
[ BASE @ HEX ]
>R 0 0 <# 2DROP R@ 1000000 U/ FF AND 0 #S [CHAR] . HOLD
2DROP R@ 10000 U/ FF AND 0 #S [CHAR] . HOLD
2DROP R@ 100 U/ FF AND 0 #S [CHAR] . HOLD
2DROP R> FF AND 0 #S
#>
[ BASE ! ]
( addr u -- IPab IPae ior )
Получить список IP multihomed-хоста
IPab IPae возвращаются в формате для последующего цикла DO, см. ConnectHost
иначе пустой хост S" " дает ior=0
( addr u verify s -- namea nameu cert )
addr u - имя файла с сертификатом и закрытым ключем в PEM-формате
( addr -- addr1 u1 )
SocketReadLine читает строку, ограниченную LF или CRLF
Сам ограничитель в возвращаемую строку не включается.
Если строка достигла размера буфера, но разделитель не
найден, то строка режется на текущей длине. Остаток будет
выдаваться следующими вызовами этой функции.
Если разделитель не найден, и в буфере еще есть куда
читать, то продолжается реальное чтение из сокета
(возможно блокирующее).
Error: "source/~ac/lib/lin/curl/curl.f.docbook" not found.
Error: "source/~ac/lib/win/arc/gzip/zlib.f.docbook" not found.
Error: "source/~profit/lib/7zip-dll.f.docbook" not found.
( addr -- addr1 u1 )
получить строку addr1 u1 из строки со счетчиком addr
счетчик - ячейчка, а не байт, в отличие от обычного COUNT
( xt node1 -- )
Применить xt ко всем элементам списка node1
xt: ( node -- ) \ xt получает параметром каждый элемент на нетронутом стеке
( xt node -- )
Применить xt к данным всех элементов списка node1
xt: ( node.car -- ) \ xt получает параметром car ячейку каждого элемента на нетронутом стеке
( xt node1 -- node2 )
Вызвать xt для каждого элемента списка
Если xt возвращает 0 - элемент удаляется из списка (память занимаемая самой ячейкой освобождается)
Иначе остаётся
Возвращается результирующий список
xt: ( node -- ? ) \ TRUE - remain, FALSE - free node
( xt node -- node1 -1 | empty-list 0 )
Поиск по списку
В случае успеха (xt вернул -1) возвращается node1 на которой поиск был остановлен
иначе - пустой список
xt: ( node -- ? ) \ TRUE - stop scan, FALSE - continue
( val node -- node1 )
Вариация с использованием динамического xt
тут используем тот факт что axt=> работает на чистом стеке то есть можно
передавать параметр node в bac4th-вызов и возвращать результат из вызова напрямую на стеке
( xt node -- )
Модифицировать каждый элемент списка с помощью xt
xt: ( node-car -- val ) \ val будет записано в текущий обрабатываемый элемент списка
( list -- xt )
создать xt который при каждом вызове будет оставлять на стеке очередной элемент списка
xt: ( -- node1 )
( node1 list -- )
Вставить элемент node1 в список list после первого элемента
если list пуст - ничего не делать
list->...->nil
list->node1->...->nil
( xt node1 -- )
применить xt последовательно к парам соседних элементов
и сохранить результат в элемент списка
При этом весь список укорачивается на один элемент
xt: ( node1-car node2-car )
( xt node1 -- )
применить xt последовательно к каждым двум соседним элементам
xt: ( node1-car node2-car )
Error: "source/~pinka/samples/2003/common/QSORT.F.docbook" not found.
( a b --> c \ <-- flag )
Цикл двоичного поиска. Выдаёт значения c и ожидает получить флаг,
указывающий куда ему идти дальше (если щуп найдёт то что нужно,
то это должна будет обработать внешняя процедура).
Каждый нырок этого слова -- это закидывание щупа и определение
где его кинуть в следующий раз
На входе: начальный диапазон (a,b)
( a b res --> x \ x flag <-- x' )
Ищет в диапазоне (a,b) такое значение x, что функция
(записанная в шитом коде после неё) равна res
Если найдено flag=TRUE и x -- значение, где f(x)=res
Если не найдено, то flag=FALSE и x -- равно либо
floor(x'), где f(x')=res, либо равно одному из краевых
значений если искомого значения аргумента вообще нет в
заданном диапазоне.
Только для линейных функций, само собой.
PRO .. CONT не работают из-за того что PREDICATE .. SUCCEEDS тоже используют L-стек
поэтому адрес успеха сохраняем в локальной переменной и вызываем вручную
( n --> n / n <-- )
Не изменяя стек при прямом проходе, на откатном ходу кладёт на стек сохранённое значение вершины стека
: RESTB ( n --> n / n <-- ) R> OVER >R ENTER R> ; (
POP EBX
PUSH EAX
CALL EBX
MOV -4 [EBP] , EAX
POP EAX
LEA EBP, -4 [EBP]
Аналог RESTB для двойных значений
: 2RESTB ( d --> d / d <-- ) R> -ROT 2DUP 2>R ROT ENTER 2R> ; (
POP EBX
PUSH [EBP]
PUSH EAX
CALL EBX
MOV -4 [EBP] , EAX
POP EAX
LEA EBP, -8 [EBP]
POP [EBP]
( a b <--> b a )
Откатываемый SWAP, т.е. выполняет SWAP и на прямом и на обратном ходу,
откатывая стек к начальному положению
( a b --> a b \ b a <-- a b )
SWAP при откате, т.е. на прямом ходу ничего не делает, на обратном ходу
-- выполняет SWAP.
( n --> n / <-- n )
DROP при откате, этим словом можно приводить одиночные значения на стеке
к итерируемым значениям, нужных для некоторых агрегаторов (типа seq{ }seq)
Восстановление значения переменной addr при откате
: KEEP ( addr --> / <-- ) R> SWAP DUP @ 2>R ENTER 2R> SWAP ! ; (
POP EBX
PUSH EAX
MOV EAX , [EAX]
PUSH EAX
MOV EAX , 0 [EBP]
LEA EBP , 4 [EBP]
CALL EBX
POP EBX
POP EDX
MOV [EDX] , EBX
( n addr --> / <-- )
Запись значения в переменную addr с восстановлением при откате
: KEEP! ( n addr --> / <-- ) R> OVER DUP @ 2>R -ROT ! ENTER 2R> SWAP ! ; (
Задать действия при откате ( BACK .. TRACKING ), или, иначе говоря,
положить адрес начала последовательности шитого кода между словами
BACK ... TRACKING на стек возвратов
Восстановление стека
Нужно для обеспечения баланса стека при прямом и обратном ходе, при наличии таких
опасных процедур как отсечения (NOT: -NOT или CUT: -CUT)
Почему-то у mlg в дипломке согласно иллюстрации OTHER делает так (я несколько месяцев честно пытался понять этот перехлёст):
: OTHER ?COMP N0T ?PAIRS >RESOLVE2 POSTPONE (-NOT) ; IMMEDIATE
но должно так:
( intermed -- )
Выдача промежуточного накапливаемого в данный момент значения агрегатора
из накопителя
( agg succ -- )
Во время исполнения на стеке должно лежать значение которое надо
при-обработать к начальному (добавить, сконкатенировать, умножить и т.д.)
Блок AMONG ... EACH ... ITERATE
порождается код:
(among) (among>) {addr} ... (each) ... (iterate) addr: код_за_циклом
Адрес (AMONG>)
При откате убрать указатель трассы итератора
Указатель начала трассы итератора
(AMONG>): успех цикла при неуспехе итератора
Адрес тела цикла
Новый адрес конца трассы итератора
При откате убрать адрес конца трассы
и саму трассу итератора
Убрать адрес кода, находящегося за циклом
Указатели на начало и конец трассы итератора
Сохранить указатели трассы итератора
Убрать новый указатель начала трассы и
восстановить старые указатели
при откате
Адрес конца и длина трассы итератора
Новый адрес начала трассы итератора
Отвести место на стеке возвратов
Скопировать трассу итератора
( addr u -- xt )
создаём виртуальный кодофайл
подключаем словарь с своими структурами управления
компилируем строку в виртуальный кодофайл
отключаем его по окончании компиляции
ставим команду выхода
оставляем исполняемый адрес начала кодофайла
( addr u --> xt \ <-- )
компилируем строку, берём исполняемый адрес кода
по окончании обработки очистить кодофайл
и кидаем его наверх
Error: "source/~yz/lib/hash.f.docbook" not found.
( CADDR N ADDR -)
PLACE AND STRING FOR SYSTEM IF NEEDED
NOT NEEDED FOR SWIFTFORTH V 2.00.3, NEEDED FOR WIN32FORTH V 4.10
VERSIONS OF /STRING AND ANEW IF SYSTEM DOESN'T HAVE THEM
: /STRING ( A N K - A+K N-K) ( OVER MIN) TUCK - >R CHARS + R> ;
( -- )
ENTER FILENAME
NOT VALID, TRY (NOT) AGAIN
VALID FILE, INIT TRANSFORM
GET BYTESIZE OF INPUT FILE
DEC CNT BY 2 FOR CR|LF EOF
DISPLAY FILESIZE TO SCREEN
SAVE MESSAGE CNT ON RETURN
COMPUTE NBLOCKS & REMBYTES
DO N FULL BLOCKS
READ REMAINING BYTES
DO IF REMBYTES > 55
DO LAST BLOCK
SHOW MD5 HASH FOR FILE
CLOSE THE INPUT FILE
( CADDR N ADDR -)
PLACE AND STRING FOR SYSTEM IF NEEDED
NOT NEEDED FOR SWIFTFORTH V 2.00.3, NEEDED FOR WIN32FORTH V 4.10
( A N CHAR - A K A+K N-K)
VERSIONS OF /STRING AND ANEW IF SYSTEM DOESN'T HAVE THEM
: /STRING ( A N K - A+K N-K) ( OVER MIN) TUCK - >R CHARS + R> ;
: ANEW >IN @ BL WORD FIND IF EXECUTE ELSE DROP THEN >IN ! MARKER ;
( -- )
ENTER FILENAME
NOT VALID, TRY (NOT) AGAIN
VALID FILE, INIT TRANSFORM
GET BYTESIZE OF INPUT FILE
DEC CNT BY 2 FOR CR|LF EOF
DISPLAY FILESIZE TO SCREEN
SAVE MESSAGE CNT ON RETURN
COMPUTE NBLOCKS & REMBYTES
DO N FULL BLOCKS
READ REMAINING BYTES
DO IF REMBYTES > 55
DO LAST BLOCK
SHOW MD5 HASH FOR FILE
CLOSE THE INPUT FILE
----------------------------------------
Формат универсальной таблицы:
+0 cell число записей
+4 cell текущий указатель
+8 ... данные
( dx dy win \ [ 4 CELLS ] rect -- ex ey )
высчитывает полный размер окна по размеру клиентской области
+ высота статуса + высота панели инструмента
( parameters interface_pointer method_number -- result )
interface_pointer, он же oid, будет передаваться первым параметром неявно
как в C++
( oid -- addr u )
здесь oid - com'овский указатель на указатель vtable
т.е. тот, что первым параметром в вызовах
( type -- flag )
65532 CONSTANT SQL_LONGVARBINARY \ -4
65535 CONSTANT SQL_LONGVARCHAR \ -1
65530 CONSTANT SQL_TINYINT \ -6
: SqlIsBinary ( type -- flag ) DUP 65531 65535 WITHIN SWAP 5 = OR ;
Error: "source/~ac/lib/lin/sql/sqlite3.f.docbook" not found.
( S" key" S" section" S" file" -- S" value" )
получить значение ключа из ini-файла (без раскрытия {})
( S" key" S" section" S" file" -- S" value" )
получить значение ключа из ini-файла
получить строку без раскрытия
раскрыть макросы в строке
освободить буфер
( xs -- addr1 u1 )
получить строку addr1 u1 из строки со счетчиком xs
счетчик - ячейчка, а не байт, в отличие от обычного COUNT
( str strlen wc wclen -- n )
addr1 u1 - строка
addr2 u2 - маска ( шаблон)
n = 0, если строка подходит под шаблон,
n = -1, - если несовпадающий символ НЕ найден, но строки разной длины.
- если он найден, причем первый несовпадающий символ
строки имеет меньшее числовое значение, чем соответсвующий
символ маски
n = 1 в остальных случаях, т.е. если первый несовпадающий символ
строки имеет не большее числовое значение, чем соответсвующий
символ маски.
Маска :
* - любое количество любых символов
? - любой символ
( a u a-subs u-subs -- a2 u2 true | a u false )
искать в строке a u подстроку a-subs u-subs
если найдена, вернуть часть строки после найденного образа и true
иначе вернуть a u false.
Error: "source/~ac/lib/string/regexp.f.docbook" not found.
Error: "source/~ac/lib/string/bregexp/bregexp.f.docbook" not found.
( a u a-key u-key -- a-right u-right a-left u-left true | a u false )
разделить строку a u на часть слева от подстроки a-key u-key
и на часть справа от этой подстроки.
( a u a-key u-key -- a-left u-left a-right u-right true | a u false )
вариант дает более 'логичный' порядок на выходе: левая_часть правая_часть
( c-addr u -- c-addr-left u-left c-addr-right u-right )
'FORCE' значит, что без флага
если разделитель не найден, то правая часть имеет длину 0.
white как бы имеет длину ноль (т.е., он остается в правой части)
( a u f <--> a1 )
находит в строке a u все символы, на которых функция f даст TRUE и генерирует вызовы для каждого символа
Функция f ( с -- 0|-1 ) получает на входе значение символа и выводит логическое значение
( a u f <--> addr u )
разбивает строку a u символами, на которых функция f даст TRUE и генерирует
вызов для каждого *отрезка* в строке a u
( c-addr u fam -- fileid ior )
В отличие от предыдущей функции здесь не просто разрешается
удаление открытого файла, но и указывается на необходимость его
автоматического удаления при закрытии всех его хэндлов.
Это похоже на CREATE-FILE-SHARED-DELETE+(сразу)DELETE-FILE при
создании файла-флага, но позволяет работать с этим смертником (читать-писать).
( fileid -- ior )
Reposition the file identified by fileid to end of file.
see also ~pinka\lib\FileExt.f # TOEND-FILE
Error: "source/~ac/lib/lin/xml/xml.f.docbook" not found.
Error: "source/~ac/lib/lin/xml/xslt.f.docbook" not found.
Error: "source/~ac/lib/lin/tidy/tidy.f.docbook" not found.