\ $Id: zstring.f,v 1.1 2003/01/18 09:02:11 anfilat Exp $
\ Нуль-строки. Технология взята из _yz\common.f

\ Копирует строку addr u по адресу z. В конец строки записывает 0
: CZMOVE ( a # z --) 2DUP + >R SWAP CMOVE R> 0 SWAP C! ;

: ALITERAL  R> COUNT OVER + 1+ >R ;

\ VOCABULARY ZStrSupport
\ GET-CURRENT ALSO ZStrSupport DEFINITIONS

USER toadr  USER fromadr  USER counter
: zchar ( --c/0) counter @ 1 <
  IF 0 ELSE -1 counter +! fromadr @ C@ fromadr 1+! THEN ;
: unchar  counter 1+! -1 fromadr +! ;
: c> ( c--) toadr @ C!  toadr 1+! ;
: escape ( c--c )
  DUP [CHAR] n = IF DROP 10 ELSE
    DUP [CHAR] r = IF DROP 13 ELSE
      DUP [CHAR] t = IF DROP 9 ELSE
       DUP [CHAR] b = IF DROP 8 ELSE
        DUP [CHAR] q = IF DROP [CHAR] " ELSE
          DUP [ CHAR 0 1- ] LITERAL OVER < SWAP [ CHAR 9 1+ ] LITERAL < AND IF
            [CHAR] 0 -
            BEGIN ( n) zchar DUP
              [ CHAR 0 1- ] LITERAL OVER < SWAP [ CHAR 9 1+ ] LITERAL < AND
            WHILE
              ( n c) [CHAR] 0 - SWAP 10 * +
            REPEAT
            0<> IF unchar THEN
          THEN
        THEN
       THEN
      THEN
    THEN
  THEN
;
: ESC-CZMOVE ( a # to --)
  toadr ! counter ! fromadr !
  BEGIN
    zchar
    DUP [CHAR] \ = IF DROP zchar escape THEN
  DUP c> 0= UNTIL ;


\ SET-CURRENT

: Z\LITERAL ( addr u -- \ a) \ в режиме интерпретации возвращает адрес
\ буфера в динамической памяти. Буфер желательно освободить
  STATE @ IF
    POSTPONE ALITERAL
    HERE 1+ DUP >R ESC-CZMOVE
    R@ ASCIIZ> NIP 2+ DUP ALLOT 2- R> 1- C!
  ELSE
    DUP 1+ ALLOCATE THROW DUP >R ESC-CZMOVE R>
  THEN
; IMMEDIATE

: ZLITERAL ( addr u -- \ a)
  STATE @ IF
    POSTPONE ALITERAL
    DUP C,
    HERE SWAP DUP ALLOT MOVE 0 C,
  ELSE
    DUP 1+ ALLOCATE THROW DUP >R CZMOVE R>
  THEN
; IMMEDIATE

\ Создает строку, оканчивающуюся нулем
: Z" ( -->") [CHAR] " PARSE [COMPILE] ZLITERAL ; IMMEDIATE

\ Создает 0-строку, при этом преобразует ее по C-правилам.
: Z\" ( -->") [CHAR] " PARSE [COMPILE] Z\LITERAL ; IMMEDIATE

\ PREVIOUS
