.ad 8
.bm 8
.fm 4
.bt $Copyright by SAP AG, 2003$$Page %$
.tm 12
.hm 6
.hs 3
.TT 1 $SQL$Project Distributed Database System$VBD05$
.tt 2 $$$
.TT 3 $JuergenP$filesysteminterface_5$$2000-10-26$
***********************************************************
.nf
 
 
    ========== licence begin  GPL
    Copyright (C) 2000 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
 
.fo
.nf
.sp
MODULE  : filesysteminterface_5
=========
.sp
Purpose : bytestring primitives
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              b05copy_bytestr (VAR t : tgg00_TransContext;
                    VAR source_file : tgg00_FileId;
                    from_pos        : tsp00_Int4;
                    VAR target_file : tgg00_FileId;
                    to_pos          : tsp00_Int4;
                    length          : tsp00_Int4;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              b05expand_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    length          : tsp00_Int4;
                    fill_char       : char;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              b05find_substring (VAR t : tgg00_TransContext;
                    VAR file_id      : tgg00_FileId;
                    start_pos        : tsp00_Int4;
                    stop_pos         : tsp00_Int4;
                    VAR patt         : tgg00_Lkey;
                    with_patt        : boolean;
                    VAR from_str_pos : tsp00_Int4;
                    VAR to_str_pos   : tsp00_Int4);
 
        PROCEDURE
              b05get_str_version  (VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    VAR str_version : tsp00_Int4);
 
        PROCEDURE
              b05length_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    VAR filelength  : tsp00_Int4;
                    VAR page_count  : tsp00_Int4;
                    VAR str_version : tsp00_Int4);
 
        PROCEDURE
              b05read_bytestr (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    pos         : tsp00_Int4;
                    VAR length  : tsp00_Int4;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4);
 
        PROCEDURE
              b05trunc_bytestr ( VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    new_filelength  : tsp00_Int4;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              b05write_bytestr(VAR t : tgg00_TransContext;
                    VAR file_id     : tgg00_FileId;
                    pos             : tsp00_Int4;
                    length          : tsp00_Int4;
                    buf_size        : tsp00_Int4;
                    buf_addr        : tsp00_MoveObjPtr     (*ptocSynonym const void**);
                    bufpos          : tsp00_Int4;
                    new_str_version : tsp00_Int4);
 
        PROCEDURE
              bd05Prefetch (
                    VAR trans    : tgg00_TransContext;
                    VAR fileId   : tgg00_FileId;
                    blobPosition : tsp00_Int4);
              (*ptocExport hbd05_1.h*)
 
        PROCEDURE
              b05finish_load (rightmost_leaf : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b05init_load (VAR rightmost_leaf : tsp00_PageNo;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b05load_string (VAR lnptr : tbd_node_ptrs;
                    VAR nptr     : tbd_node_ptrs;
                    VAR left_pno : tsp00_PageNo;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b05save_quick (VAR pno : tsp00_PageNo;
                    VAR nptr    : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
&       ifdef TRACE
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01basis_error (layer : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
 
        PROCEDURE
              t01int4 (layer : tgg00_Debug;
                    nam : tsp00_Sname;
                    l   : tsp00_Int4);
 
        PROCEDURE
              t01lkey (layer : tgg00_Debug;
                    VAR k : tgg00_Lkey);
 
        PROCEDURE
              t01moveobj (layer : tgg00_Debug;
                    VAR b   : tsp00_MoveObj;
                    start_p : tsp00_Int4;
                    stop_p  : tsp00_Int4);
 
        PROCEDURE
              t01name (layer : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01p2int4 (debug : tgg00_Debug;
                    nam_1 : tsp00_Sname;
                    int_1 : tsp00_Int4;
                    nam_2 : tsp00_Sname;
                    int_2 : tsp00_Int4);
 
        PROCEDURE
              t01str30 (layer : tgg00_Debug;
                    str30 : tsp00_C30);
 
        PROCEDURE
              t01treeid (layer : tgg00_Debug;
                    nam        : tsp00_Sname;
                    VAR treeid : tgg00_FileId);
&       endif
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        VAR
              b01downfilesystem : boolean;
 
      ------------------------------ 
 
        FROM
              error_text_handling : VBD06;
 
        PROCEDURE
              b06illegal_root_access (VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              Trace : VBD120;
 
        PROCEDURE
              b120InsertTrace (VAR t   : tgg00_TransContext;
                    trace_layer  : tgg00_Debug;
                    trace_object : tgg00_VtraceType;
                    body_len     : tsp00_Int2;
                    trace_body   : tgg11_VtraceBodyPtr);
 
      ------------------------------ 
 
        FROM
              nodehandling : VBD13;
 
        PROCEDURE
              b13free_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              bd13GetNode (VAR Current : tbd_current_tree;
                    Pno          : tsp00_PageNo;
                    PageLockMode : tbd00_PageLockMode;
                    NodeReq      : tbd_node_request;
                    VAR Nptrs    : tbd_node_ptrs);
 
        PROCEDURE
              b13init_default_data_page (
                    VAR Trans   : tgg00_TransContext;
                    VAR FileId  : tgg00_FileId;
                    Level       : tsp00_Int2;
                    NewPno      : tsp00_PageNo;
                    VAR Nptrs   : tbd_node_ptrs);
 
        PROCEDURE
              b13r_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree;
                    lru_info    : tbd_lru_info);
 
        PROCEDURE
              b13w_release_node (VAR nptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              filedirectory : VBD17;
 
        PROCEDURE
              b17state_fdir (VAR fn : tgg00_Filename;
                    VAR fi      : tbd_fileinfo;
                    shared_file : boolean;
                    VAR t       : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              treehandling : VBD30;
 
        PROCEDURE
              b30cinit_current (VAR t : tgg00_TransContext;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30current (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId;
                    m_type      : tgg00_MessType;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b30set_read_only (VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              bytestring_handling : VBD60;
 
        PROCEDURE
              b60conlput_bstrleaf (VAR nptr : tbd_node_ptrs;
                    pos           : tsp00_Int4;
                    length        : tsp00_Int4;
                    VAR b         : tsp00_Page;
                    VAR firstcall : boolean;
                    extended      : boolean;
                    VAR filelen   : tsp00_Int4;
                    VAR current   : tbd_current_tree);
 
        PROCEDURE
              b60get_bytestr (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60extend_bytestr (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60lput_bstrleaf (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    extended    : boolean;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60read_bytestr (nptr : tbd_nodeptr;
                    pos      : tsp00_Int4;
                    length   : tsp00_Int4;
                    buf_size : tsp00_Int4;
                    buf_addr : tsp00_MoveObjPtr;
                    buf_pos  : tsp00_Int4;
                    VAR e    : tgg00_BasisError);
 
        PROCEDURE
              b60rext_bstrroot (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b60rput_bstrroot (VAR nptr : tbd_node_ptrs;
                    pos         : tsp00_Int4;
                    length      : tsp00_Int4;
                    use_buf     : boolean;
                    fill_char   : char;
                    buf_size    : tsp00_Int4;
                    buf_addr    : tsp00_MoveObjPtr;
                    bufpos      : tsp00_Int4;
                    extended    : boolean;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              bytestring_indexhandling : VBD61;
 
        PROCEDURE
              b61add_bstrindex (VAR act_rootptr : tbd_node_ptrs;
                    act_pno     : tsp00_PageNo;
                    pno_1       : tsp00_PageNo;
                    pno_2       : tsp00_PageNo;
                    ins_level   : tsp00_Int2;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b61first_load_step (VAR leftptr : tbd_node_ptrs;
                    VAR leafptr : tbd_node_ptrs;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b61rtrunc_bstrroot (VAR nptr : tbd_node_ptrs;
                    new_flength : tsp00_Int4;
                    VAR current : tbd_current_tree);
 
        PROCEDURE
              b61search_leaf (VAR nptr : tbd_node_ptrs;
                    pos          : tsp00_Int4;
                    VAR leaf_pos : tsp00_Int4;
                    VAR current  : tbd_current_tree);
 
        PROCEDURE
              b61trunc_bstr (VAR nptr : tbd_node_ptrs;
                    new_flength : tsp00_Int4;
                    destroy     : boolean;
                    VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              ref_statistic : VBD73;
 
        PROCEDURE
              b73cmd_count (statement_kind : tgg00_RefInfoIndex);
 
      ------------------------------ 
 
        FROM
              concurrency : VBD75;
 
        PROCEDURE
              b75tlwrite_lock_tree (VAR current : tbd_current_tree;
                    leaf            : tsp00_PageNo;
                    VAR lock_return : tbd_lock_returncode;
                    suspend_reason  : tsp00_Int2);
 
        PROCEDURE
              b75tuwrite_unlock_tree (VAR current : tbd_current_tree);
 
        PROCEDURE
              b75turead_unlock_tree (VAR current : tbd_current_tree);
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        PROCEDURE
              bd999CheckSpace(
                    VAR Trans         : tgg00_TransContext;
                    NumPagesRequestes : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01vtrace : tgg_vtrace_state;
 
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG10;
 
        PROCEDURE
              g10mv (mod_id : tsp_c6;
                    mod_intern_num : tsp_int4;
                    source_upb     : tsp_int4;         destin_upb : tsp_int4;
                    VAR source     : tsp_moveobj;      source_pos : tsp_int4;
                    VAR destin     : tgg11_VtraceBody; destin_pos : tsp_int4;
                    length         : tsp_int4;
                    VAR e          : tgg_basis_error);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
        PROCEDURE
              s30cmp (VAR n      : tbd_node;
                    fieldpos1    : tsp_int4;
                    fieldlength1 : tsp_int4;
                    VAR pattern  : tsp00_Key;
                    fieldpos2    : tsp_int4;
                    fieldlength2 : tsp_int4;
                    VAR l_result : tsp_lcomp_result);
 
        FUNCTION
              s30lenl (VAR n : tbd_node;
                    val  : char;
                    pos  : tsp_int4;
                    stop : tsp_int4) : tsp_int4;
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              g10mv;
 
              tsp_moveobj tgg11_VtraceBody
 
        PROCEDURE
              s30cmp;
 
              tsp_moveobj tbd_node
              tsp_moveobj tsp00_Key
 
        FUNCTION
              s30lenl;
 
              tsp_moveobj tbd_node
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1984-08-07
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-10-26
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
 
.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
 
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      c_use_buffer = true;
 
TYPE
 
      tbd05_bstr_comp = RECORD
            b_nptr  : tbd_node_ptrs;
            b_nstop : tsp00_Int4;
            b_pno1  : tsp00_PageNo;
            b_pno2  : tsp00_PageNo;
            b_curr  : tbd_current_tree;
            b_first : boolean
      END;
 
 
      tbd05_bstr_info = RECORD
            b_nptr : tbd_node_ptrs;
            b_fpos : tsp00_Int4;
            b_flen : tsp00_Int4;
            b_curr : tbd_current_tree
      END;
 
 
      tbd05_closure_elem = RECORD
            ce_strpos  : tsp00_Int4;
            ce_act_pno : tsp00_PageNo;
            ce_n_pos   : tsp00_Int4;
            ce_p_pos   : tsp00_Int4
      END;
 
 
      tbd05_pattern_info = RECORD
            pi_pattern      : tgg00_Lkey;
            pi_with_pattern : boolean;
            pi_subbeg       : tsp00_Int4;
            pi_subend       : tsp00_Int4;
            pi_sublen       : tsp00_Int4
      END;
 
 
 
(*------------------------------*) 
 
PROCEDURE
      b05copy_bytestr (VAR t : tgg00_TransContext;
            VAR source_file : tgg00_FileId;
            from_pos        : tsp00_Int4;
            VAR target_file : tgg00_FileId;
            to_pos          : tsp00_Int4;
            length          : tsp00_Int4;
            new_str_version : tsp00_Int4);
 
VAR
      lock_return    : tbd_lock_returncode;
      old_error      : tgg00_BasisError;
      source_nptr    : tbd_node_ptrs;
      dest_nptr      : tbd_node_ptrs;
      source_flength : tsp00_Int4;
      dest_flength   : tsp00_Int4;
      act_maxflen    : tsp00_Int4;
      source_info    : tbd05_bstr_info;
      dest_info      : tbd05_bstr_info;
      source_current : tbd_current_tree;
      dest_current   : tbd_current_tree;
      trace          : tgg11_BdIntTrace;
      root_trace     : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := from_pos;
    trace.bdiInt_gg11 [1]   := to_pos;
    trace.bdiInt_gg11 [2]   := length;
    b120InsertTrace (t, bd, b05copy, sizeof (trace), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30  (bi, '====> bd copy bytestr         ');
t01treeid (bi, 'source file ', source_file);
t01treeid (bi, 'target file ', target_file);
t01p2int4 (bi, 'from pos    ', from_pos
      ,        'to pos      ', to_pos);
t01p2int4 (bi, 'length      ', length
      ,        'str version ', new_str_version);
&endif
(* PTS 1003033 E.Z. *)
b30cinit_current (t, source_current);
b30cinit_current (t, dest_current);
WITH source_info DO
    BEGIN
    b_nptr.np_ptr   := NIL;
    b_nptr.np_cbptr := NIL
    END;
(*ENDWITH*) 
WITH dest_info DO
    BEGIN
    b_nptr.np_ptr   := NIL;
    b_nptr.np_cbptr := NIL
    END;
(*ENDWITH*) 
WITH source_nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL
    END;
(*ENDWITH*) 
WITH dest_nptr DO
    BEGIN
    np_ptr   := NIL;
    np_cbptr := NIL
    END;
(*ENDWITH*) 
t.trError_gg00 := e_ok;
WITH t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        IF  source_file.fileName_gg00 = target_file.fileName_gg00
        THEN
            trError_gg00 := e_not_implemented
        ELSE
            BEGIN
            WITH target_file DO
                fileBdUse_gg00 := fileBdUse_gg00 + [bd_write_acc];
            (*ENDWITH*) 
            bd999CheckSpace (t, (length DIV MAX_BSTR_COVERING_BD00) + 1);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                b30current (t, source_file, m_column, source_current);
                IF  trError_gg00 = e_ok
                THEN
                    b30current (t, target_file, m_column, dest_current)
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  (source_current.curr_tree_id.fileRoot_gg00 = NIL_PAGE_NO_GG00) OR
            (dest_current.curr_tree_id.fileRoot_gg00 = NIL_PAGE_NO_GG00  )
        THEN
            trError_gg00 := e_file_empty
        ELSE
            IF  ((length < 1) OR (length > cbd_cspmaxint4_mxspbuf))
                AND
                (length <> cgg_whole_bytestr)
            THEN
                trError_gg00 := e_file_limit
            ELSE
                IF  (from_pos < 1                     ) OR
                    (from_pos > cbd_cspmaxint4_mxspbuf)
                THEN
                    trError_gg00 := e_file_limit
                ELSE
                    IF  (to_pos <> cgg_eo_bytestr       ) AND
                        (
                        (to_pos < 1                     ) OR
                        (to_pos > cbd_cspmaxint4_mxspbuf)
                        )
                    THEN
                        trError_gg00 := e_file_limit
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        root_trace.bdrRoot_gg11 := dest_current.curr_tree_id.fileRoot_gg00;
        b75tlwrite_lock_tree (source_current, source_current.curr_tree_id.fileRoot_gg00,
              lock_return, 31);
        bd13GetNode (source_current, source_current.curr_tree_id.fileRoot_gg00,
              plmNoLock_ebd00, nr_for_read, source_nptr);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b75tlwrite_lock_tree (dest_current, dest_current.curr_tree_id.fileRoot_gg00,
                  lock_return, 32);
            bd13GetNode (dest_current, dest_current.curr_tree_id.fileRoot_gg00,
                  plmNoLock_ebd00, nr_for_update, dest_nptr);
            IF  trError_gg00 = e_file_must_be_read_only
            THEN
                BEGIN
                IF  dest_nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (dest_nptr, dest_current,
                          lru_normal);
                (*ENDIF*) 
                b30set_read_only (dest_current);
                IF  trError_gg00 = e_ok
                THEN
                    bd13GetNode (dest_current, dest_current.curr_tree_id.fileRoot_gg00,
                          plmNoLock_ebd00, nr_for_update, dest_nptr);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        source_flength := source_nptr.np_ptr^.ndStrFileSize_bd00;
        dest_flength   := dest_nptr.np_ptr^.ndStrFileSize_bd00;
        IF  length = cgg_whole_bytestr
        THEN
            length := source_flength;
        (*ENDIF*) 
        from_pos := from_pos - 1;
        IF  to_pos = cgg_eo_bytestr
        THEN
            to_pos := dest_flength
        ELSE
            to_pos := to_pos - 1;
        (*ENDIF*) 
        IF  (from_pos + length) > source_flength
        THEN
            BEGIN
            length := source_flength - from_pos;
&           ifdef TRACE
            t01int4 (bi, 'trunc length', length);
&           endif
            END;
        (* PTS 1001460 Torsten Strahl 1998-08-02 *)
        (*ENDIF*) 
        IF  (from_pos > source_flength                 ) OR
            (to_pos > dest_flength                     ) OR
            (
            ((to_pos + length) > cbd_cspmaxint4_mxspbuf)
            )
        THEN
            trError_gg00 := e_file_limit
        ELSE
            BEGIN
            act_maxflen := (dest_flength - 1) DIV MAX_BSTR_COVERING_BD00;
            act_maxflen := (act_maxflen + 1) * MAX_BSTR_COVERING_BD00;
            WITH source_info DO
                BEGIN
                b_nptr := source_nptr;
                b_flen := source_flength;
                b_curr := source_current;
                b_fpos := from_pos
                END;
            (*ENDWITH*) 
            WITH dest_info DO
                BEGIN
                b_nptr := dest_nptr;
                b_flen := dest_flength;
                b_curr := dest_current;
                b_fpos := to_pos
                END;
            (*ENDWITH*) 
            (* *)
            (* assign new string version to root of dest file *)
            (* *)
            (* PTS 1001460 Torsten Strahl 1998-08-02 *)
            IF  new_str_version <> NIL_STR_VERSION_GG00
            THEN
                dest_nptr.np_ptr^.nd_str_version := new_str_version;
            (*ENDIF*) 
            bd05copy_2 (source_info, dest_info, length, act_maxflen);
            dest_nptr   := dest_info.b_nptr;
            source_nptr := source_info.b_nptr
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        source_file := source_current.curr_tree_id;
        target_file := dest_current.curr_tree_id
        END;
    (*ENDIF*) 
    WITH target_file DO
        fileBdUse_gg00 := fileBdUse_gg00 - [bd_write_acc];
    (*ENDWITH*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        old_error := trError_gg00;
        b06illegal_root_access (source_current);
        IF  (trError_gg00 = old_error) AND (source_file.fileName_gg00 <> target_file.fileName_gg00)
        THEN
            b06illegal_root_access (dest_current);
        (*ENDIF*) 
        IF  source_nptr.np_ptr <> NIL
        THEN
            b13r_release_node (source_nptr, source_current, lru_normal);
        (*ENDIF*) 
        IF  dest_nptr.np_ptr <> NIL
        THEN
            b13r_release_node (dest_nptr, dest_current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
WITH source_current DO
    IF  curr_lockstate = w_lock_tree
    THEN
        b75tuwrite_unlock_tree (source_current)
    ELSE
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (source_current);
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDWITH*) 
WITH dest_current DO
    IF  curr_lockstate = w_lock_tree
    THEN
        b75tuwrite_unlock_tree (dest_current)
    ELSE
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (dest_current);
&       ifdef TRACE
        (*ENDIF*) 
    (*ENDIF*) 
(*ENDWITH*) 
t01basis_error (bi, 'copy bst err', t.trError_gg00);
&endif
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05copy, sizeof (root_trace), @root_trace)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05expand_bytestr (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            length          : tsp00_Int4;
            fill_char       : char;
            new_str_version : tsp00_Int4);
 
VAR
      extended         : boolean;
      updated_new      : boolean;
      lock_return      : tbd_lock_returncode;
      pos              : tsp00_Int4;
      expand_length    : tsp00_Int4;
      part_length      : tsp00_Int4;
      last_page_length : tsp00_Int4;
      nptr             : tbd_node_ptrs;
      flength          : tsp00_Int4;
      trace            : tgg11_BdIntTrace;
      root_trace       : tgg11_BdRootTrace;
      current          : tbd_current_tree;
      DummyBuffer      : tsp00_Buf;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := length;
    b120InsertTrace (t, bd, b05expand,
          sizeof (trace)
          - sizeof (trace.bdiInt_gg11 [1])
          - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30  (bi, '====> bd expand bytstr        ');
t01treeid (bi, 'treeid      ', file_id);
t01int4   (bi, 'length      ', length);
&endif
b30cinit_current (t, current);
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
t.trError_gg00      := e_ok;
extended      := true;
updated_new   := false;
lock_return   := lock_okay;
(* PTS 1003033 E.Z. *)
IF  b01downfilesystem
THEN
    t.trError_gg00 := e_shutdown
ELSE
    WITH current, curr_tree_id, t DO
        BEGIN
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
        bd999CheckSpace (t, (length DIV MAX_BSTR_COVERING_BD00) + 1);
        IF  trError_gg00 = e_ok
        THEN
            b30current (t, file_id, m_column, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  fileRoot_gg00 = NIL_PAGE_NO_GG00
            THEN
                trError_gg00 := e_file_empty
            ELSE
                IF  length < 1
                THEN
                    trError_gg00 := e_buffer_limit
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := fileRoot_gg00;
            b75tlwrite_lock_tree (current, fileRoot_gg00, lock_return, 33);
            bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_update, nptr);
            IF  trError_gg00 = e_file_must_be_read_only
            THEN
                BEGIN
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal);
                (*ENDIF*) 
                b30set_read_only (current);
                IF  trError_gg00 = e_ok
                THEN
                    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                          nr_for_update, nptr);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            flength := nptr.np_ptr^.ndStrFileSize_bd00;
            pos     := flength;
&           ifdef TRACE
            t01int4 (bd_byte, 'flength     ', flength);
&           endif
            IF  length > flength
            THEN
                BEGIN
                IF  flength <> 0
                THEN
                    last_page_length := ((flength - 1)
                          MOD MAX_BSTR_COVERING_BD00) + 1
                ELSE
                    last_page_length := 0;
                (*ENDIF*) 
                expand_length := length - flength;
                IF  expand_length <= MAX_BSTR_COVERING_BD00 -
                    last_page_length
                THEN
                    part_length := expand_length
                ELSE
                    BEGIN
                    IF  last_page_length = MAX_BSTR_COVERING_BD00
                    THEN
                        IF  expand_length > MAX_BSTR_COVERING_BD00
                        THEN
                            part_length := MAX_BSTR_COVERING_BD00
                        ELSE
                            part_length := expand_length
                        (*ENDIF*) 
                    ELSE
                        part_length := MAX_BSTR_COVERING_BD00 -
                              last_page_length
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                REPEAT
                    IF  (last_page_length + part_length)
                        <= MAX_BSTR_COVERING_BD00
                    THEN
                        BEGIN
                        (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                        IF  new_str_version <> NIL_STR_VERSION_GG00
                        THEN
                            nptr.np_ptr^.nd_str_version := new_str_version;
                        (*ENDIF*) 
                        IF  flength <= MAX_BSTR_COVERING_BD00
                        THEN
                            b60rput_bstrroot (nptr, pos,
                                  part_length, NOT c_use_buffer,
                                  fill_char, sizeof (DummyBuffer), @DummyBuffer, 1,
                                  extended, current)
                        ELSE
                            b60lput_bstrleaf (nptr, pos,
                                  part_length, NOT c_use_buffer,
                                  fill_char, sizeof (DummyBuffer), @DummyBuffer, 1,
                                  extended, current)
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        updated_new := true;
                        (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                        IF  new_str_version <> NIL_STR_VERSION_GG00
                        THEN
                            nptr.np_ptr^.nd_str_version := new_str_version;
                        (*ENDIF*) 
                        IF  flength <= MAX_BSTR_COVERING_BD00
                        THEN
                            b60rext_bstrroot (nptr, pos,
                                  part_length, NOT c_use_buffer,
                                  fill_char, sizeof (DummyBuffer), @DummyBuffer, 1, current)
                        ELSE
                            b60extend_bytestr (nptr, pos,
                                  part_length, NOT c_use_buffer,
                                  fill_char, sizeof (DummyBuffer), @DummyBuffer, 1, current);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    pos           := pos + part_length;
                    flength       := flength + part_length;
                    expand_length := expand_length - part_length;
                    IF  expand_length < MAX_BSTR_COVERING_BD00
                    THEN
                        part_length := expand_length
                    ELSE
                        part_length := MAX_BSTR_COVERING_BD00;
                    (*ENDIF*) 
                    last_page_length := MAX_BSTR_COVERING_BD00;
                UNTIL
                    (trError_gg00 <> e_ok) OR (expand_length = 0);
                (*ENDREPEAT*) 
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    IF  nptr.np_ptr^.nd_id <> fileRoot_gg00
                    THEN
                        BEGIN
                        b13w_release_node (nptr, current);
                        IF  trError_gg00 = e_ok
                        THEN
                            bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                                  nr_for_update, nptr);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        nptr.np_ptr^.ndStrFileSize_bd00 := length - expand_length;
                        b13w_release_node (nptr, current)
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE
                b13r_release_node (nptr, current, lru_normal)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            file_id := curr_tree_id
        ELSE
            b06illegal_root_access (current);
        (*ENDIF*) 
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
        IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (current)
        ELSE
            IF  curr_lockstate = w_lock_tree
            THEN
                b75tuwrite_unlock_tree (current)
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
&ifdef TRACE
t01basis_error (bi, 'expand bst e', t.trError_gg00);
&endif
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05expand, sizeof (root_trace), @root_trace)
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05find_substring (VAR t : tgg00_TransContext;
            VAR file_id      : tgg00_FileId;
            start_pos        : tsp00_Int4;
            stop_pos         : tsp00_Int4;
            VAR patt         : tgg00_Lkey;
            with_patt        : boolean;
            VAR from_str_pos : tsp00_Int4;
            VAR to_str_pos   : tsp00_Int4);
 
VAR
      npos       : tsp00_Int4;
      nptr       : tbd_node_ptrs;
      patt_info  : tbd05_pattern_info;
      current    : tbd_current_tree;
      trace      : tgg11_BdIntTrace;
      root_trace : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := start_pos;
    trace.bdiInt_gg11 [1]   := stop_pos;
    b120InsertTrace (t, bd, b05find, sizeof (trace)- sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd find substring ');
t01treeid (bi, 'treeid      ', file_id);
t01int4   (bi, 'start_pos   ', start_pos);
t01int4   (bi, 'stop_pos    ', stop_pos);
t01lkey   (bi, patt);
&endif
(* PTS 1003033 E.Z. *)
b30cinit_current (t, current);
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
t.trError_gg00      := e_ok;
WITH current, curr_tree_id, t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        b30current (t, file_id, m_column, current);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  fileRoot_gg00 = NIL_PAGE_NO_GG00
        THEN
            trError_gg00 := e_file_empty
        ELSE
            IF  (start_pos < 1) OR (start_pos > cbd_cspmaxint4_mxspbuf)
            THEN
                trError_gg00 := e_file_limit
            ELSE
                IF  (stop_pos <> cgg_eo_bytestr) AND
                    ((stop_pos < 1) OR
                    (stop_pos > cbd_cspmaxint4_mxspbuf))
                THEN
                    trError_gg00 := e_file_limit
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        root_trace.bdrRoot_gg11 := fileRoot_gg00;
        bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
              nr_for_read, nptr);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  stop_pos = cgg_eo_bytestr
            THEN
                stop_pos := nptr.np_ptr^.ndStrFileSize_bd00
            ELSE
                stop_pos := stop_pos - 1;
            (*ENDIF*) 
            start_pos := start_pos - 1;
            IF  stop_pos > nptr.np_ptr^.ndStrFileSize_bd00
            THEN
                trError_gg00 := e_file_limit
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (start_pos <= stop_pos)
        THEN
            BEGIN
            WITH patt_info DO
                BEGIN
                pi_pattern      := patt;
                pi_with_pattern := with_patt
                END;
            (*ENDWITH*) 
            IF  with_patt
            THEN
                bd05get_substring (patt_info)
            ELSE
                WITH patt_info DO
                    BEGIN
                    pi_subbeg := 1;
                    pi_subend := pi_pattern.len;
                    pi_sublen := pi_pattern.len
                    END;
                (*ENDWITH*) 
            (*ENDIF*) 
            IF  nptr.np_ptr^.ndStrFileSize_bd00 <= MAX_BSTR_COVERING_BD00
            THEN
                npos := start_pos
            ELSE
                b61search_leaf (nptr, start_pos, npos, current);
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                bd05search_substring (nptr, npos, start_pos + 1,
                      stop_pos + 1, patt_info, from_str_pos,
                      to_str_pos, current)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            file_id := curr_tree_id
        ELSE
            b06illegal_root_access (current);
        (*ENDIF*) 
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  curr_lockstate = r_lock_tree
    THEN
        b75turead_unlock_tree (current);
    (*ENDIF*) 
    END;
(*ENDWITH*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05find, sizeof (root_trace), @root_trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01int4        (bi, 'from pos    ', from_str_pos);
t01int4        (bi, 'to pos      ', to_str_pos);
t01basis_error (bi, 'find sub err', t.trError_gg00);
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05finish_load (rightmost_leaf : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
VAR
      rootptr : tbd_node_ptrs;
      nptr    : tbd_node_ptrs;
 
BEGIN
rootptr.np_ptr   := NIL;
rootptr.np_cbptr := NIL;
nptr             := rootptr;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    bd13GetNode (current, rightmost_leaf, plmNoLock_ebd00,
          nr_for_read, nptr);
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
              nr_for_update, rootptr);
        IF  trError_gg00 = e_ok
        THEN
            WITH rootptr, np_ptr^ DO
                BEGIN
                ndStrFileSize_bd00    := nptr.np_ptr^.ndStrFileSize_bd00;
                nd_str_version := NIL_STR_VERSION_GG00;
                b13w_release_node (rootptr, current)
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  (trError_gg00 <> e_ok) AND (rootptr.np_ptr <> NIL)
    THEN
        b13r_release_node (rootptr, current, lru_normal)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05get_str_version  (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            VAR str_version : tsp00_Int4);
 
VAR
      nptr       : tbd_node_ptrs;
      current    : tbd_current_tree;
      root_trace : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    b120InsertTrace (t, bd, b05getset, 0, @root_trace);
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd bytestr get ver');
t01treeid (bi, 'treeid      ', file_id);
&endif
b30cinit_current (t, current);
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
t.trError_gg00      := e_ok;
WITH current, curr_tree_id, t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        BEGIN
        b30current (t, file_id, m_column, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  fileRoot_gg00 <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                root_trace.bdrRoot_gg11 := fileRoot_gg00;
                bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                      nr_for_read, nptr);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    str_version := nptr.np_ptr^.nd_str_version;
                    file_id     := curr_tree_id
                    END
                ELSE
                    b06illegal_root_access (current);
                (*ENDIF*) 
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal);
                (*ENDIF*) 
                END
            ELSE
                trError_gg00 := e_file_empty
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (current)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
    THEN
        BEGIN
        root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
        root_trace.bdrError_gg11  := t.trError_gg00;
        b120InsertTrace (t, bd, b05getset, sizeof (root_trace), @root_trace)
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01int4        (bi, 'str version ', str_version);
    t01basis_error (bi, 'getset error', t.trError_gg00);
&   endif
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05init_load (VAR rightmost_leaf : tsp00_PageNo;
            VAR current : tbd_current_tree);
 
BEGIN
rightmost_leaf := current.curr_tree_id.fileRoot_gg00
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05length_bytestr (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            VAR filelength  : tsp00_Int4;
            VAR page_count  : tsp00_Int4;
            VAR str_version : tsp00_Int4);
 
VAR
      nptr       : tbd_node_ptrs;
      current    : tbd_current_tree;
      root_trace : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    b120InsertTrace (t, bd, b05length, 0, @root_trace);
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd bytestr length ');
t01treeid (bi, 'treeid      ', file_id);
&endif
(* PTS 1003033 E.Z. *)
b30cinit_current (t, current);
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
t.trError_gg00      := e_ok;
WITH current, curr_tree_id, t DO
    BEGIN
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        BEGIN
        b30current (t, file_id, m_column, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  fileRoot_gg00 <> NIL_PAGE_NO_GG00
            THEN
                BEGIN
                root_trace.bdrRoot_gg11 := fileRoot_gg00;
                bd13GetNode (current, fileRoot_gg00,
                      plmNoLock_ebd00, nr_for_read, nptr);
                IF  trError_gg00 = e_ok
                THEN
                    WITH nptr, np_ptr^ DO
                        BEGIN
                        filelength  := ndStrFileSize_bd00;
                        str_version := nd_str_version;
                        file_id     := curr_tree_id;
                        page_count  := 1 + (* root page *)
                              nd_level +
                              (filelength DIV (PNOS_PER_PAGE_BD00 * MAX_BSTR_COVERING_BD00)) +
                              (filelength DIV MAX_BSTR_COVERING_BD00 )
                        END
                    (*ENDWITH*) 
                ELSE
                    b06illegal_root_access (current);
                (*ENDIF*) 
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal)
                (*ENDIF*) 
                END
            ELSE
                trError_gg00 := e_file_empty
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (current);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
    THEN
        BEGIN
        root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
        root_trace.bdrError_gg11  := t.trError_gg00;
        b120InsertTrace (t, bd, b05length, sizeof (root_trace), @root_trace)
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01p2int4      (bi, 'filelength  ', filelength
          ,             'str version ', str_version);
    t01basis_error (bi, 'length error', t.trError_gg00);
&   endif
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05load_string (VAR lnptr : tbd_node_ptrs;
            VAR nptr     : tbd_node_ptrs;
            VAR left_pno : tsp00_PageNo;
            VAR current  : tbd_current_tree);
 
VAR
      save_bottom : tgg00_PagePos;
      rootptr     : tbd_node_ptrs;
      act_pno     : tsp00_PageNo;
 
BEGIN
rootptr.np_ptr   := NIL;
rootptr.np_cbptr := NIL;
WITH current, curr_tree_id, curr_trans^ DO
    BEGIN
    IF  lnptr.np_ptr^.nd_id = fileRoot_gg00
    THEN
        BEGIN
        b61first_load_step (lnptr, nptr, current);
        left_pno := NIL_PAGE_NO_GG00
        END
    ELSE
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            IF  nptr.np_ptr^.nd_bottom > BODY_BEG_BD00
            THEN
                BEGIN
                WITH nptr.np_ptr^ DO
                    BEGIN
                    save_bottom        := nd_bottom;
                    b13init_default_data_page (curr_trans^, curr_tree_id, LEAF_LEVEL_BD00, nd_id, nptr);
                    nd_bottom          := save_bottom;
                    nd_left            := lnptr.np_ptr^.nd_id;
                    ndStrFileSize_bd00 := lnptr.np_ptr^.ndStrFileSize_bd00 + nd_bottom - BODY_BEG_BD00;
                    act_pno            := nd_id
                    END;
                (*ENDWITH*) 
                lnptr.np_ptr^.nd_right := nptr.np_ptr^.nd_id
                END
            ELSE
                act_pno := NIL_PAGE_NO_GG00
            (*ENDIF*) 
        ELSE
            act_pno := NIL_PAGE_NO_GG00;
        (*ENDIF*) 
        IF  left_pno = NIL_PAGE_NO_GG00
        THEN
            left_pno := nptr.np_ptr^.nd_id
        ELSE
            BEGIN
            bd13GetNode (current, fileRoot_gg00,
                  plmNoLock_ebd00, nr_for_update, rootptr);
            IF  trError_gg00 = e_ok
            THEN
                b61add_bstrindex (rootptr, fileRoot_gg00, left_pno, act_pno,
                      succ(LEAF_LEVEL_BD00), current);
            (*ENDIF*) 
            left_pno := NIL_PAGE_NO_GG00
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND (nptr.np_ptr <> NIL)
        THEN
            IF  nptr.np_ptr^.nd_bottom > BODY_BEG_BD00
            THEN
                BEGIN
                b13w_release_node (lnptr, current);
                lnptr         := nptr;
                nptr.np_ptr   := NIL;
                nptr.np_cbptr := NIL
                END
            ELSE
                b13free_node (nptr, current)
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  trError_gg00 <> e_ok
    THEN
        BEGIN
        IF  nptr.np_ptr <> NIL
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  lnptr.np_ptr <> NIL
        THEN
            b13r_release_node (lnptr, current, lru_normal);
        (*ENDIF*) 
        IF  rootptr.np_ptr <> NIL
        THEN
            b13r_release_node (rootptr, current, lru_normal)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05read_bytestr (VAR t : tgg00_TransContext;
            VAR file_id : tgg00_FileId;
            pos         : tsp00_Int4;
            VAR length  : tsp00_Int4;
            buf_size    : tsp00_Int4;
            buf_addr    : tsp00_MoveObjPtr;
            bufpos      : tsp00_Int4);
 
VAR
      leaf_pos   : tsp00_Int4;
      flength    : tsp00_Int4;
      nptr       : tbd_node_ptrs;
      trace      : tgg11_BdIntTrace;
      root_trace : tgg11_BdRootTrace;
      current    : tbd_current_tree;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := pos;
    trace.bdiInt_gg11 [1]   := length;
    b120InsertTrace (t, bd, b05read, sizeof (trace) - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30  (bi, '====> bd read bytestr         ');
t01treeid (bi, 'treeid      ', file_id);
t01int4   (bi, 'pos         ', pos);
t01int4   (bi, 'length      ', length);
t01int4   (bi, 'bufpos      ', bufpos);
&endif
b30cinit_current (t, current);
nptr.np_ptr    := NIL;
nptr.np_cbptr  := NIL;
t.trError_gg00 := e_ok;
b73cmd_count (iread_string);
IF  b01downfilesystem
THEN
    t.trError_gg00 := e_shutdown
ELSE
    WITH current, curr_tree_id, t DO
        BEGIN
        b30current (t, file_id, m_column, current);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  fileRoot_gg00 = NIL_PAGE_NO_GG00
            THEN
                trError_gg00 := e_file_empty
            ELSE
                IF  (length < 1) OR (length + bufpos - 1 > buf_size)
                THEN
                    trError_gg00 := e_buffer_limit
                ELSE
                    IF  (pos < 1) OR (pos > cbd_cspmaxint4_mxspbuf)
                    THEN
                        trError_gg00 := e_file_limit
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := fileRoot_gg00;
            bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                  nr_for_read, nptr);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                flength := nptr.np_ptr^.ndStrFileSize_bd00;
                pos     := pos - 1;
                IF  pos < flength
                THEN
                    BEGIN
                    IF  (pos + length) > flength
                    THEN
                        BEGIN
                        length := flength - pos;
&                       ifdef TRACE
                        t01int4 (bi, 'trunc length', length);
&                       endif
                        END;
                    (*ENDIF*) 
                    IF  ((pos MOD MAX_BSTR_COVERING_BD00) + length)
                        < MAX_BSTR_COVERING_BD00
                    THEN
                        BEGIN
                        IF  flength <= MAX_BSTR_COVERING_BD00
                        THEN
                            BEGIN
                            leaf_pos := pos;
                            b60read_bytestr (nptr.np_ptr, leaf_pos,
                                  length, buf_size, buf_addr, bufpos,
                                  trError_gg00)
                            END
                        ELSE
                            BEGIN
                            b61search_leaf (nptr, pos, leaf_pos,
                                  current);
                            IF  trError_gg00 = e_ok
                            THEN
                                b60read_bytestr (nptr.np_ptr, leaf_pos,
                                      length, buf_size, buf_addr,
                                      bufpos, trError_gg00)
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        b61search_leaf (nptr, pos, leaf_pos, current);
                        IF  trError_gg00 = e_ok
                        THEN
                            b60get_bytestr (nptr, leaf_pos, length,
                                  buf_size, buf_addr, bufpos, current)
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  nptr.np_ptr <> NIL
                    THEN
                        b13r_release_node (nptr, current, lru_normal)
                    (*ENDIF*) 
                    END
                ELSE
                    IF  (flength = 0) OR (pos = flength)
                    THEN
                        BEGIN
                        length := 0;
                        trError_gg00 := e_key_not_found
                        END
                    ELSE
                        trError_gg00 := e_file_limit
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                file_id := curr_tree_id
            ELSE
                b06illegal_root_access (current);
            (*ENDIF*) 
            IF  nptr.np_ptr <> NIL
            THEN
                b13r_release_node (nptr, current, lru_normal)
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (current);
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
&ifdef TRACE
IF  t.trError_gg00 = e_ok
THEN
    t01moveobj (bi, buf_addr^, 1, length);
(*ENDIF*) 
t01basis_error (bi, 'read bstr er', t.trError_gg00);
&endif
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05read, sizeof (root_trace), @root_trace)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05save_quick (VAR pno : tsp00_PageNo;
            VAR nptr    : tbd_node_ptrs;
            VAR current : tbd_current_tree);
 
VAR
      leafpos : tsp00_Int4;
 
BEGIN
WITH current, curr_tree_id, curr_trans^, nptr DO
    BEGIN
    IF  pno = fileRoot_gg00
    THEN
        BEGIN
        bd13GetNode (current, pno, plmNoLock_ebd00, nr_for_read, nptr);
        IF  trError_gg00 = e_ok
        THEN
            b61search_leaf (nptr, 1, leafpos, current)
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        IF  np_ptr = NIL
        THEN
            BEGIN
            IF  pno <> NIL_PAGE_NO_GG00
            THEN
                bd13GetNode (current, pno, plmNoLock_ebd00, nr_for_read, nptr);
            (*ENDIF*) 
            END
        ELSE
            BEGIN
            b13r_release_node (nptr, current, lru_last);
            IF  pno <> NIL_PAGE_NO_GG00
            THEN
                bd13GetNode (current, pno, plmNoLock_ebd00, nr_for_read, nptr);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  np_ptr <> NIL
    THEN
        IF  trError_gg00 = e_ok
        THEN
            pno := np_ptr^.nd_right
        ELSE
            b13r_release_node (nptr, current, lru_normal)
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05trunc_bytestr ( VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            new_filelength  : tsp00_Int4;
            new_str_version : tsp00_Int4);
 
VAR
      lock_return : tbd_lock_returncode;
      nptr        : tbd_node_ptrs;
      current     : tbd_current_tree;
      trace       : tgg11_BdIntTrace;
      root_trace  : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11    := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]   := new_filelength;
    b120InsertTrace (t, bd, b05trunc,
          sizeof (trace)
          - sizeof (trace.bdiInt_gg11 [1])
          - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, 'bd trunc bytestr  ');
t01treeid (bi, 'treeid      ', file_id);
t01p2int4 (bi, 'new flength ', new_filelength
      ,        'str version ', new_str_version);
&endif
(* PTS 1003033 E.Z. *)
b30cinit_current (t, current);
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
t.trError_gg00      := e_ok;
WITH current, curr_tree_id, t DO
    BEGIN
    curr_lockstate := no_bd_lock;
    IF  b01downfilesystem
    THEN
        trError_gg00 := e_shutdown
    ELSE
        BEGIN
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
        b30current (t, file_id, m_column, current)
        END;
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        BEGIN
        IF  fileRoot_gg00 <> NIL_PAGE_NO_GG00
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := fileRoot_gg00;
            b75tlwrite_lock_tree (current, fileRoot_gg00, lock_return, 30);
            bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                  nr_for_update, nptr);
            IF  trError_gg00 = e_file_must_be_read_only
            THEN
                BEGIN
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal);
                (*ENDIF*) 
                b30set_read_only (current);
                IF  trError_gg00 = e_ok
                THEN
                    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                          nr_for_update, nptr);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                IF  new_str_version <> NIL_STR_VERSION_GG00
                THEN
                    nptr.np_ptr^.nd_str_version := new_str_version;
                (*ENDIF*) 
                IF  new_filelength < nptr.np_ptr^.ndStrFileSize_bd00
                THEN
                    BEGIN
                    IF  nptr.np_ptr^.ndStrFileSize_bd00 <= MAX_BSTR_COVERING_BD00
                    THEN
                        b61rtrunc_bstrroot (nptr, new_filelength,
                              current)
                    ELSE
                        b61trunc_bstr (nptr, new_filelength, false,
                              current)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                file_id := curr_tree_id
            ELSE
                b06illegal_root_access (current);
            (*ENDIF*) 
            IF  nptr.np_ptr <> NIL
            THEN
                b13r_release_node (nptr, current, lru_normal)
            (*ENDIF*) 
            END
        ELSE
            trError_gg00 := e_file_empty
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
    IF  curr_lockstate = w_lock_tree
    THEN
        b75tuwrite_unlock_tree (current)
    ELSE
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (current);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
    THEN
        BEGIN
        root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
        root_trace.bdrError_gg11  := t.trError_gg00;
        b120InsertTrace (t, bd, b05trunc, sizeof (root_trace), @root_trace)
        END;
&   ifdef TRACE
    (*ENDIF*) 
    t01basis_error (bi, 'trunc bstr e', t.trError_gg00);
&   endif
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      b05write_bytestr (VAR t : tgg00_TransContext;
            VAR file_id     : tgg00_FileId;
            pos             : tsp00_Int4;
            length          : tsp00_Int4;
            buf_size        : tsp00_Int4;
            buf_addr        : tsp00_MoveObjPtr;
            bufpos          : tsp00_Int4;
            new_str_version : tsp00_Int4);
 
VAR
      extended         : boolean;
      fill_char        : char;
      lock_return      : tbd_lock_returncode;
      leaf_pos         : tsp00_Int4;
      trace_str_len    : tsp00_Int4;
      ext_length       : tsp00_Int4;
      last_page_length : tsp00_Int4;
      nptr             : tbd_node_ptrs;
      flength          : tsp00_Int4;
      trace            : tgg11_BdWriteStrTrace;
      root_trace       : tgg11_BdRootTrace;
      current          : tbd_current_tree;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrRoot_gg11             := NIL_PAGE_NO_GG00;
    trace.bdwsHead_gg11.bdwhTrType_gg11 := bdtrWriteStr_egg11;
    trace.bdwsHead_gg11.bdwhPos_gg11    := pos;
    trace.bdwsHead_gg11.bdwhLen_gg11    := length;
    trace_str_len                       := length;
    IF  sizeof (trace.bdwsHead_gg11) + trace_str_len > sizeof (tgg11_VtraceBody)
    THEN
        trace_str_len := sizeof (tgg11_VtraceBody) - sizeof (trace.bdwsHead_gg11);
    (*ENDIF*) 
    g10mv ('VBD05 ',   1,    
          buf_size,  sizeof (trace.bdwsStr_gg11),
          buf_addr^, bufpos, trace.bdwsStr_gg11, 1, trace_str_len, t.trError_gg00);
    b120InsertTrace (t, bd, b05write, sizeof (trace.bdwsHead_gg11) + trace_str_len, @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01str30   (bi, '====> bd write bytestr        ');
t01treeid  (bi, 'treeid      ', file_id);
t01int4    (bi, 'pos         ', pos);
t01int4    (bi, 'length      ', length);
t01moveobj (bi, buf_addr^, bufpos, bufpos + length - 1);
&endif
b30cinit_current (t, current);
nptr.np_ptr   := NIL;
nptr.np_cbptr := NIL;
t.trError_gg00      := e_ok;
fill_char     := bsp_c1;
lock_return   := lock_okay;
b73cmd_count (iwrite_string);
IF  b01downfilesystem
THEN
    t.trError_gg00 := e_shutdown
ELSE
    WITH current, curr_tree_id, t DO
        BEGIN
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 + [bd_write_acc];
        bd999CheckSpace (t, 3);
        IF  trError_gg00 = e_ok
        THEN
            b30current (t, file_id, m_column, current);
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            IF  fileRoot_gg00 = NIL_PAGE_NO_GG00
            THEN
                trError_gg00 := e_file_empty
            ELSE
                IF  (length < 1                      ) OR
                    (length > buf_size               ) OR
                    ((bufpos + length - 1) > buf_size)
                THEN
                    trError_gg00 := e_buffer_limit
                ELSE
                    IF  (pos <> cgg_eo_bytestr       ) AND
                        (
                        (pos < 1                     ) OR
                        (pos > cbd_cspmaxint4_mxspbuf)
                        )
                    THEN
                        trError_gg00 := e_file_limit
                    (*ENDIF*) 
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            root_trace.bdrRoot_gg11 := fileRoot_gg00;
            b75tlwrite_lock_tree (current, fileRoot_gg00, lock_return, 34);
            bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_update, nptr);
            IF  trError_gg00 = e_file_must_be_read_only
            THEN
                BEGIN
                IF  nptr.np_ptr <> NIL
                THEN
                    b13r_release_node (nptr, current, lru_normal);
                (*ENDIF*) 
                b30set_read_only (current);
                IF  trError_gg00 = e_ok
                THEN
                    bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00,
                          nr_for_update, nptr);
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            flength := nptr.np_ptr^.ndStrFileSize_bd00;
            IF  pos = cgg_eo_bytestr
            THEN
                pos := flength
            ELSE
                pos := pos - 1;
            (*ENDIF*) 
&           ifdef TRACE
            t01int4 (bd_byte, 'pos         ', pos);
            t01int4 (bd_byte, 'flength     ', flength);
&           endif
            IF  (pos > flength                           ) OR
                ((pos + length) >= cbd_cspmaxint4_mxspbuf)
            THEN
                trError_gg00 := e_file_limit
            ELSE
                BEGIN
                IF  flength <> 0
                THEN
                    last_page_length := ((flength - 1)
                          MOD MAX_BSTR_COVERING_BD00) + 1
                ELSE
                    last_page_length := 0;
                (*ENDIF*) 
                ext_length := flength - pos;
                ext_length := length - ext_length;
                leaf_pos   := pos MOD MAX_BSTR_COVERING_BD00;
                IF  ext_length > 0
                THEN
                    extended := true
                ELSE
                    extended := false;
                (*ENDIF*) 
                IF  (last_page_length + ext_length)
                    <= MAX_BSTR_COVERING_BD00
                THEN
                    BEGIN
                    (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                    IF  new_str_version <> NIL_STR_VERSION_GG00
                    THEN
                        nptr.np_ptr^.nd_str_version := new_str_version;
                    (*ENDIF*) 
                    IF  flength <= MAX_BSTR_COVERING_BD00
                    THEN
                        b60rput_bstrroot (nptr, pos, length,
                              c_use_buffer, fill_char, buf_size,
                              buf_addr, bufpos, extended, current)
                    ELSE
                        b60lput_bstrleaf (nptr, pos, length,
                              c_use_buffer, fill_char, buf_size,
                              buf_addr, bufpos, extended, current)
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    (* PTS 1001460 Torsten Strahl 1998-08-02 *)
                    IF  new_str_version <> NIL_STR_VERSION_GG00
                    THEN
                        nptr.np_ptr^.nd_str_version := new_str_version;
                    (*ENDIF*) 
                    IF  flength <= MAX_BSTR_COVERING_BD00
                    THEN
                        b60rext_bstrroot (nptr, pos, length,
                              c_use_buffer, fill_char, buf_size,
                              buf_addr, bufpos, current)
                    ELSE
                        b60extend_bytestr (nptr, pos, length,
                              c_use_buffer, fill_char, buf_size,
                              buf_addr, bufpos, current)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  trError_gg00 = e_ok
        THEN
            file_id := curr_tree_id
        ELSE
            b06illegal_root_access (current);
        (*ENDIF*) 
        file_id.fileBdUse_gg00 := file_id.fileBdUse_gg00 - [bd_write_acc];
        IF  (trError_gg00 <> e_ok) AND (nptr.np_ptr <> NIL)
        THEN
            b13r_release_node (nptr, current, lru_normal);
        (*ENDIF*) 
        IF  curr_lockstate = r_lock_tree
        THEN
            b75turead_unlock_tree (current)
        ELSE
            IF  curr_lockstate = w_lock_tree
            THEN
                b75tuwrite_unlock_tree (current);
            (*ENDIF*) 
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
&ifdef TRACE
t01basis_error (bi, 'write bst er', t.trError_gg00);
&endif
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    root_trace.bdrTrType_gg11 := bdtrRoot_egg11;
    root_trace.bdrError_gg11  := t.trError_gg00;
    b120InsertTrace (t, bd, b05write, sizeof (root_trace), @root_trace)
    END;
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05Prefetch (
            VAR trans    : tgg00_TransContext;
            VAR fileId   : tgg00_FileId;
            blobPosition : tsp00_Int4);
 
VAR
      leafPosition : tsp00_Int4;
      nextLeaf     : tsp00_Int4;
      nptrs        : tbd_node_ptrs;
      fileInfo     : tbd_fileinfo;
      current      : tbd_current_tree;
      trace        : tgg11_BdIntTrace;
      rootTrace    : tgg11_BdRootTrace;
 
BEGIN
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    rootTrace.bdrRoot_gg11 := NIL_PAGE_NO_GG00;
    trace.bdiTrType_gg11   := bdtrInt_egg11;
    trace.bdiInt_gg11 [0]  := blobPosition;
    trace.bdiInt_gg11 [1]  := 0;
    b120InsertTrace (trans, bd, b05read, sizeof (trace) - sizeof (trace.bdiInt_gg11 [2]), @trace)
    END;
&ifdef TRACE
(*ENDIF*) 
t01name   (bi, '====> bd prefetch ');
t01treeid (bi, 'fileId      ', fileId);
t01int4   (bi, 'blob pos    ', blobPosition);
&endif
IF  b01downfilesystem
THEN
    trans.trError_gg00 := e_shutdown
ELSE
    WITH trans, current, curr_tree_id DO
        BEGIN
        trError_gg00    := e_ok;
        nptrs.np_ptr    := NIL;
        nptrs.np_cbptr  := NIL;
        nextLeaf        := NIL_PAGE_NO_GG00;
        b17state_fdir (fileId.fileName_gg00, fileInfo, ftsShared_egg00 IN fileId.fileType_gg00, trans);
        IF  trError_gg00 = e_ok
        THEN
            BEGIN
            b30current (trans, fileId, m_column, current);
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                bd13GetNode (current, fileRoot_gg00, plmNoLock_ebd00, nr_for_read, nptrs);
                IF  trError_gg00 = e_ok
                THEN
                    BEGIN
                    b61search_leaf (nptrs, blobPosition, leafPosition, current);
                    WHILE (trError_gg00 = e_ok) AND (nptrs.np_ptr <> NIL) DO
                        BEGIN
                        nextLeaf := nptrs.np_ptr^.nd_right;
                        b13r_release_node (nptrs, current, lru_normal);
                        IF  nextLeaf <> NIL_PAGE_NO_GG00
                        THEN
                            bd13GetNode (current, nextLeaf, plmNoLock_ebd00, nr_for_read, nptrs);
                        (*ENDIF*) 
                        END
                    (*ENDWHILE*) 
                    END;
                (*ENDIF*) 
                IF  nptrs.np_ptr <> NIL
                THEN
                    b13r_release_node (nptrs, current, lru_normal);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  current.curr_lockstate = r_lock_tree
            THEN
                b75turead_unlock_tree (current)
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
IF  g01vtrace.vtrAll_gg00 OR g01vtrace.vtrBdString_gg00
THEN
    BEGIN
    rootTrace.bdrTrType_gg11 := bdtrRoot_egg11;
    rootTrace.bdrError_gg11  := trans.trError_gg00;
    b120InsertTrace (trans, bd, b05read, sizeof (rootTrace), @rootTrace);
    END;
(*ENDIF*) 
trans.trError_gg00 := e_ok; (* ignore all errors *)
END;
 
(*========== locals ============*)
(*------------------------------*) 
 
PROCEDURE
      bd05copy_2 (VAR source_info : tbd05_bstr_info;
            VAR dest_info : tbd05_bstr_info;
            length        : tsp00_Int4;
            flen_max      : tsp00_Int4);
 
VAR
      firstcall  : boolean;
      extended   : boolean;
      fill_char  : char;
      act_root   : tsp00_PageNo;
      f_lpos     : tsp00_Int4;
      remain_len : tsp00_Int4;
      act_len    : tsp00_Int4;
      t          : tgg00_TransContextPtr;
      Buffer     : tsp00_Page;
 
BEGIN
extended  := false;
firstcall := true;
fill_char := bsp_c1;
act_root  := dest_info.b_nptr.np_ptr^.nd_id;
t         := dest_info.b_curr.curr_trans;
WITH source_info DO
    IF  b_flen > MAX_BSTR_COVERING_BD00
    THEN
        b61search_leaf (b_nptr, b_fpos, f_lpos, b_curr)
    ELSE
        f_lpos := b_fpos;
    (*ENDIF*) 
(*ENDWITH*) 
IF  (act_root = source_info.b_curr.curr_tree_id.fileRoot_gg00) AND
    (source_info.b_flen > MAX_BSTR_COVERING_BD00             ) AND
    (t^.trError_gg00 = e_ok                                  )
THEN
    bd13GetNode (dest_info.b_curr, act_root, plmNoLock_ebd00,
          nr_for_update, dest_info.b_nptr);
(*ENDIF*) 
IF  t^.trError_gg00 = e_ok
THEN
    BEGIN
    remain_len := length;
    REPEAT
        IF  remain_len > sizeof (Buffer)
        THEN
            act_len := sizeof (Buffer)
        ELSE
            act_len := remain_len;
        (*ENDIF*) 
        WITH source_info DO
            IF  (f_lpos + remain_len) < MAX_BSTR_COVERING_BD00
            THEN
                b60read_bytestr (b_nptr.np_ptr, f_lpos, act_len,
                      sizeof (Buffer), @Buffer, 1, t^.trError_gg00)
            ELSE
                b60get_bytestr (b_nptr, f_lpos, act_len, sizeof (Buffer), @Buffer,
                      1, b_curr);
            (*ENDIF*) 
        (*ENDWITH*) 
        IF  t^.trError_gg00 = e_ok
        THEN
            BEGIN
            WITH dest_info DO
                BEGIN
                IF  (b_fpos + act_len) > flen_max
                THEN
                    IF  b_flen <= MAX_BSTR_COVERING_BD00
                    THEN
                        b60rext_bstrroot (b_nptr, b_fpos, act_len,
                              c_use_buffer, fill_char, sizeof (Buffer), @Buffer,
                              1, b_curr)
                    ELSE
                        BEGIN
                        IF  b_nptr.np_ptr^.nd_id <>
                            b_nptr.np_ptr^.nd_root
                        THEN
                            BEGIN
                            b13w_release_node (b_nptr, b_curr);
                            firstcall := true;
                            IF  t^.trError_gg00 = e_ok
                            THEN
                                bd13GetNode (b_curr, act_root, plmNoLock_ebd00,
                                      nr_for_update, b_nptr);
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  t^.trError_gg00 = e_ok
                        THEN
                            b60extend_bytestr (b_nptr, b_fpos, act_len,
                                  c_use_buffer, fill_char, sizeof (Buffer),
                                  @Buffer, 1, b_curr)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                ELSE
                    BEGIN
                    IF  NOT extended
                    THEN
                        extended := (b_fpos + act_len) > b_flen;
                    (*ENDIF*) 
                    IF  b_flen <= MAX_BSTR_COVERING_BD00
                    THEN
                        b60rput_bstrroot (b_nptr, b_fpos, act_len,
                              c_use_buffer, fill_char, sizeof (Buffer), @Buffer,
                              1, extended, b_curr)
                    ELSE
                        b60conlput_bstrleaf (b_nptr, b_fpos, act_len,
                              Buffer, firstcall, extended, b_flen, b_curr)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  t^.trError_gg00 = e_ok
                THEN
                    BEGIN
                    remain_len := remain_len - act_len;
                    b_fpos     := b_fpos + act_len;
                    f_lpos     :=
                          (f_lpos + act_len) MOD MAX_BSTR_COVERING_BD00;
                    IF  (b_nptr.np_ptr = NIL) AND (remain_len > 0)
                    THEN
                        BEGIN
                        firstcall := true;
                        bd13GetNode (b_curr, act_root, plmNoLock_ebd00,
                              nr_for_update, b_nptr);
                        IF  t^.trError_gg00 = e_ok
                        THEN
                            BEGIN
                            b_flen   := b_nptr.np_ptr^.ndStrFileSize_bd00;
                            flen_max := (b_flen - 1) DIV
                                  MAX_BSTR_COVERING_BD00;
                            flen_max := (flen_max + 1) *
                                  MAX_BSTR_COVERING_BD00
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
            END
        (*ENDIF*) 
    UNTIL
        (t^.trError_gg00 <> e_ok) OR (remain_len = 0);
    (*ENDREPEAT*) 
    IF  t^.trError_gg00 = e_ok
    THEN
        BEGIN
        WITH source_info DO
            IF  b_nptr.np_ptr <> NIL
            THEN
                IF  (b_nptr.np_ptr^.nd_id <>
                    dest_info.b_curr.curr_tree_id.fileRoot_gg00)
                THEN
                    b13r_release_node (b_nptr, b_curr, lru_normal);
                (*ENDIF*) 
            (*ENDIF*) 
        (*ENDWITH*) 
        WITH dest_info DO
            IF  b_nptr.np_ptr <> NIL
            THEN
                b13w_release_node (b_nptr, b_curr)
            (*ENDIF*) 
        (*ENDWITH*) 
        END
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05get_substring (VAR patt_info : tbd05_pattern_info);
 
VAR
      i : tsp00_Int4;
 
BEGIN
WITH patt_info DO
    BEGIN
    pi_sublen := 0;
    i         := 1;
    WHILE ((i <= pi_pattern.len) AND
          (pi_pattern.k [i] IN [csp_star1, csp_any1, csp_cclass])) DO
        BEGIN
        i := succ (i);
        IF  pi_pattern.k [i-1] = csp_cclass
        THEN
            i := succ(pi_pattern.len);
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    pi_subbeg := i;
    WHILE ((i <= pi_pattern.len) AND
          NOT (pi_pattern.k [i] IN [csp_star1, csp_any1, csp_cclass])) DO
        BEGIN
        pi_subend := i;
        pi_sublen := succ (pi_sublen);
        i := succ (i);
        END;
    (*ENDWHILE*) 
    IF  pi_sublen = 0
    THEN
        BEGIN
        pi_subbeg := 1;
        pi_subend := 0;
        END;
    (* *)
&   ifdef TRACE
    (*ENDIF*) 
    t01name (bd_byte, 'get_substring     ');
    t01int4 (bd_byte, 'subbeg      ', pi_subbeg);
    t01int4 (bd_byte, 'sublen      ', pi_sublen);
    t01int4 (bd_byte, 'subend      ', pi_subend);
&   endif
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05left_pattern_match (VAR n_comp : tbd05_bstr_comp;
            n_pos      : tsp00_Int4;
            VAR patt   : tsp00_Key;
            p_pos      : tsp00_Int4;
            VAR strpos : tsp00_Int4;
            VAR found  : boolean;
            rec_count  : tsp00_Int4);
      (* not recursive *)
 
VAR
      ok          : boolean;
      match       : boolean;
      shift       : boolean;
      cl_index    : tsp00_Int4;
      patt_incr   : tsp00_Int4;
      right, next : tsp00_PageNo;
      act_pno     : tsp00_PageNo;
      cl          : tbd05_closure_elem;
 
BEGIN
&ifdef TRACE
t01name (bd_byte, '==================');
t01name (bd_byte, 'lpm2 :            ');
t01int4 (bd_byte, 'nstop       ', n_comp.b_nstop);
t01int4 (bd_byte, 'bfirst      ', ord (n_comp.b_first));
t01int4 (bd_byte, 'npos        ', n_pos);
t01int4 (bd_byte, 'ppos        ', p_pos);
t01int4 (bd_byte, 'strpos      ', strpos);
t01int4 (bd_byte, 'found       ', ord (found));
&endif
shift    := false;
ok       := true;
cl_index := 0;
act_pno  := NIL_PAGE_NO_GG00;
WITH n_comp, b_curr, curr_trans^ DO
    BEGIN
    IF  p_pos < 1
    THEN
        found := true
    ELSE
        IF  (p_pos = 1               ) AND
            (
            (patt [p_pos] = csp_star1) OR
            (patt [p_pos] = csp_any1 )
            )
        THEN
            BEGIN
            found := true;
            IF  patt [p_pos] =  csp_any1
            THEN
                IF  strpos >= 1
                THEN
                    strpos := strpos - 1
                ELSE
                    found := false
                (*ENDIF*) 
            ELSE
                strpos := b_nstop - 1
            (*ENDIF*) 
            END
        ELSE
            IF  strpos < b_nstop
            THEN
                found := false
            ELSE
                BEGIN
                REPEAT
                    patt_incr := 1;
                    match     := false;
                    rec_count := rec_count + 1;
&                   ifdef TRACE
                    t01name (bd_byte, '------------------');
                    t01name (bd_byte, 'loop:             ');
                    t01int4 (bd_byte, 'shift       ', ord (shift));
                    t01int4 (bd_byte, 'npos        ', n_pos);
                    t01int4 (bd_byte, 'ppos        ', p_pos);
                    t01int4 (bd_byte, 'strpos      ', strpos);
                    t01int4 (bd_byte, 'act_pno     ', act_pno);
                    t01int4 (bd_byte, 'rec_count   ', rec_count);
&                   endif
                    IF  n_pos < BODY_BEG_BD00
                    THEN
                        BEGIN
                        next  := b_nptr.np_ptr^.nd_left;
                        right := b_nptr.np_ptr^.nd_id;
                        b13r_release_node (b_nptr, b_curr, lru_normal);
                        IF  b_first
                        THEN
                            b_pno1 := next
                        ELSE
                            b_pno2 := next;
                        (*ENDIF*) 
                        bd13GetNode (b_curr, next, plmNoLock_ebd00,
                              nr_for_read, b_nptr);
                        IF  trError_gg00 = e_ok
                        THEN
                            n_pos := MAX_BOTTOM_BD00 - 1
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        act_pno := b_nptr.np_ptr^.nd_id;
                        found   := false;
                        IF  patt [p_pos] = csp_star1
                        THEN
                            BEGIN
                            p_pos := p_pos - 1;
                            IF  p_pos = 0 (* leading csp_star1 *)
                            THEN
                                strpos := b_nstop - 1;
                            (*ENDIF*) 
                            shift         := true;
                            cl_index      := cl_index + 1;
                            cl.ce_p_pos   := p_pos;
                            cl.ce_n_pos   := 0;
                            cl.ce_strpos  := 0;
                            cl.ce_act_pno := act_pno;
                            END;
                        (*ENDIF*) 
                        IF  p_pos >= 1
                        THEN
                            BEGIN
                            IF  (patt [p_pos] =
                                b_nptr.np_ptr^.nd_body [n_pos])
                                OR
                                (patt [p_pos] = csp_any1)
                            THEN
                                match := true
                            ELSE
                                IF  patt [p_pos] = csp_cclass
                                THEN
                                    match := bd05one_c_match
                                          (patt, p_pos,
                                          b_nptr.np_ptr^.nd_body[n_pos],
                                          patt_incr, false);
                                (*ENDIF*) 
                            (*ENDIF*) 
                            IF  match
                            THEN
                                BEGIN
                                p_pos  := p_pos - patt_incr;
                                n_pos  := n_pos - 1;
                                strpos := strpos - 1;
                                IF  shift
                                THEN
                                    BEGIN
                                    cl.ce_n_pos  := n_pos;
                                    cl.ce_strpos := strpos;
                                    shift        := false
                                    END
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  shift
                                THEN
                                    BEGIN
                                    IF  (patt [p_pos] <> csp_star1)
                                    THEN
                                        BEGIN
                                        n_pos  := n_pos - 1;
                                        strpos := strpos - 1
                                        END
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    IF  cl_index = 0
                                    THEN
                                        ok := false
                                    ELSE
                                        BEGIN
                                        strpos  := cl.ce_strpos;
                                        n_pos   := cl.ce_n_pos;
                                        p_pos   := cl.ce_p_pos;
                                        act_pno := cl.ce_act_pno;
                                        shift   := true;
                                        IF  act_pno <>
                                            b_nptr.np_ptr^.nd_id
                                        THEN
                                            BEGIN
                                            right :=
                                                  b_nptr.np_ptr^.nd_id;
                                            b13r_release_node (b_nptr,
                                                  b_curr, lru_normal);
                                            IF  b_first
                                            THEN
                                                b_pno1 := act_pno
                                            ELSE
                                                b_pno2 := act_pno;
                                            (*ENDIF*) 
                                            bd13GetNode (b_curr, act_pno,
                                                  plmNoLock_ebd00,
                                                  nr_for_read, b_nptr);
                                            END
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                UNTIL
                    (p_pos < 1       ) OR
                    (strpos < b_nstop) OR
                    (trError_gg00 <> e_ok  ) OR
                    NOT ok;
                (*ENDREPEAT*) 
                IF  p_pos < 1
                THEN
                    found := true;
                (*ENDIF*) 
                IF  (strpos < b_nstop - 1) OR NOT ok
                THEN
                    found := false;
                (*ENDIF*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01int4 (bd_byte, 'lpm res     ', ord (found));
&endif
END;
 
(*------------------------------*) 
 
FUNCTION
      bd05one_c_match  (VAR pat : tsp00_Key;
            pos             : tsp00_Int4;
            comp_ch         : char;
            VAR pat_incr    : tsp00_Int4;
            right_direction : boolean) : boolean;
 
VAR
      found         : boolean;
      is_end        : boolean;
      is_error      : boolean;
      negated_class : boolean;
      step          : tsp00_Int4;
      state         : tsp00_Int4;
      left_pos      : tsp00_Int4;
      cl_start      : tsp00_Int4;
 
BEGIN
&ifdef TRACE
t01name (bd_byte, 'one_char_match    ');
t01int4 (bd_byte, 'comp_char   ', ord (comp_ch));
&endif
is_end   := false;
is_error := false;
found    := false;
state    := 1;
IF  right_direction
THEN
    step := 1
ELSE
    step := -1;
(*ENDIF*) 
IF  pat [pos] = csp_cclass
THEN
    BEGIN
    cl_start      := pos;
    negated_class := false;
    IF  right_direction
    THEN
        BEGIN
        IF  pat [pos + 1] = csp_cnot
        THEN
            BEGIN
            negated_class := true;
            pos           := pos + 1
            END
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        left_pos := pos;
        REPEAT
            left_pos := left_pos + step;
&           ifdef TRACE
            t01int4 (bd_byte, 'pat_ch      ', ord (pat [ left_pos ]));
&           endif
        UNTIL
            pat [left_pos] = csp_cclass;
        (*ENDREPEAT*) 
        negated_class := pat [left_pos + 1] = csp_cnot
        END;
    (*ENDIF*) 
    pos      := pos + step;
    WHILE NOT (found OR is_end) AND NOT is_error DO
        CASE state OF
            1 :
                BEGIN
&               ifdef TRACE
                t01name (bd_byte, 'state 1 :         ');
                t01int4 (bd_byte, 'pat_ch      ', ord (pat [ pos ]));
&               endif
                IF  pat [pos] = comp_ch
                THEN
                    found := true
                ELSE
                    IF  pat [pos] = csp_cclass
                    THEN
                        is_end := true
                    ELSE
                        IF  pat [pos] = csp_crange
                        THEN
                            is_error := true
                        ELSE
                            BEGIN
                            left_pos := pos;
                            pos      := pos + step;
                            IF  pat [pos] = csp_crange
                            THEN
                                state := 2
                            ELSE
                                IF  pat [pos] = csp_cclass
                                THEN
                                    is_end := true
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            2 :
                BEGIN
                pos := pos + step;
&               ifdef TRACE
                t01name (bd_byte, 'state 2 :         ');
                t01int4 (bd_byte, 'pat_ch      ', ord (pat [ pos ]));
&               endif
                IF  NOT (pat [pos] IN [csp_cclass, csp_crange])
                THEN
                    state := 3
                ELSE
                    is_error := true
                (*ENDIF*) 
                END;
            3 :
                BEGIN
&               ifdef TRACE
                t01name (bd_byte, 'state 3 :         ');
                t01int4 (bd_byte, 'pat_ch      ', ord (pat [ pos ]));
&               endif
                IF  pat [left_pos] <= pat [pos]
                THEN
                    found := (pat [left_pos] <= comp_ch)
                          AND
                          (pat [pos] >= comp_ch)
                ELSE
                    found := (pat [left_pos] >= comp_ch)
                          AND
                          (pat [pos] <= comp_ch);
                (*ENDIF*) 
                IF  NOT found
                THEN
                    pos := pos + step;
                (*ENDIF*) 
                state := 1
                END;
            END;
        (*ENDCASE*) 
    (*ENDWHILE*) 
    IF  found
    THEN
        BEGIN
        IF  negated_class
        THEN
            found := false
        (*ENDIF*) 
        END
    ELSE (* not found *)
        IF  negated_class
        THEN
            found := true;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  found
    THEN
        BEGIN
        WHILE pat [pos] <> csp_cclass DO
            pos := pos + step;
        (*ENDWHILE*) 
        IF  right_direction
        THEN
            pat_incr := pos - cl_start + 1
        ELSE
            pat_incr := cl_start - pos + 1
        (*ENDIF*) 
        END
    ELSE
        pat_incr := 0
    (*ENDIF*) 
    END;
&ifdef TRACE
(*ENDIF*) 
IF  is_error
THEN
    t01name (kb_qual, 'omatch error      ');
&endif
(*ENDIF*) 
bd05one_c_match := found;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05right_pattern_match (VAR n_comp : tbd05_bstr_comp;
            n_pos      : tsp00_Int4;
            VAR patt   : tgg00_Lkey;
            p_pos      : tsp00_Int4;
            VAR strpos : tsp00_Int4;
            VAR found  : boolean;
            rec_count  : tsp00_Int4);
      (* not recursive *)
 
VAR
      ok, match  : boolean;
      shift      : boolean;
      cl_index   : tsp00_Int4;
      patt_incr  : tsp00_Int4;
      left, next : tsp00_PageNo;
      act_pno    : tsp00_PageNo;
      cl         : tbd05_closure_elem;
 
BEGIN
&ifdef TRACE
t01name (bd_byte, '==================');
t01name (bd_byte, 'rpm2 :            ');
t01int4 (bd_byte, 'nstop       ', n_comp.b_nstop);
t01int4 (bd_byte, 'bfirst      ', ord (n_comp.b_first));
t01int4 (bd_byte, 'npos        ', n_pos);
t01int4 (bd_byte, 'patt.len    ', patt.len);
t01int4 (bd_byte, 'ppos        ', p_pos);
t01int4 (bd_byte, 'strpos      ', strpos);
t01int4 (bd_byte, 'found       ', ord (found));
&endif
shift    := false;
ok       := true;
cl_index := 0;
act_pno  := NIL_PAGE_NO_GG00;
WITH n_comp, b_curr, curr_trans^ DO
    BEGIN
    IF  p_pos > patt.len
    THEN
        found := true
    ELSE
        IF  (p_pos = patt.len) AND (patt.k [p_pos] = csp_star1)
        THEN
            found := true
        ELSE
            IF  strpos > b_nstop
            THEN
                found := false
            ELSE
                BEGIN
                REPEAT
                    patt_incr := 1;
                    match     := false;
                    rec_count := rec_count + 1;
&                   ifdef TRACE
                    t01name (bd_byte, '------------------');
                    t01name (bd_byte, 'loop:             ');
                    t01int4 (bd_byte, 'shift       ', ord (shift));
                    t01int4 (bd_byte, 'npos        ', n_pos);
                    t01int4 (bd_byte, 'ppos        ', p_pos);
                    t01int4 (bd_byte, 'strpos      ', strpos);
                    t01int4 (bd_byte, 'act_pno     ', act_pno);
                    t01int4 (bd_byte, 'rec_count   ', rec_count);
&                   endif
                    IF  n_pos = MAX_BOTTOM_BD00
                    THEN
                        BEGIN
                        next := b_nptr.np_ptr^.nd_right;
                        left := b_nptr.np_ptr^.nd_id;
                        b13r_release_node (b_nptr, b_curr, lru_normal);
                        IF  b_first
                        THEN
                            b_pno1 := next
                        ELSE
                            b_pno2 := next;
                        (*ENDIF*) 
                        bd13GetNode (b_curr, next, plmNoLock_ebd00,
                              nr_for_read, b_nptr);
                        IF  trError_gg00 = e_ok
                        THEN
                            n_pos := BODY_BEG_BD00
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        act_pno := b_nptr.np_ptr^.nd_id;
                        found   := false;
                        IF  patt.k [p_pos] = csp_star1
                        THEN
                            BEGIN
                            p_pos         := p_pos + 1;
                            shift         := true;
                            cl_index      := cl_index + 1;
                            cl.ce_p_pos   := p_pos;
                            cl.ce_n_pos   := 0;
                            cl.ce_strpos  := 0;
                            cl.ce_act_pno := NIL_PAGE_NO_GG00;
                            END;
                        (*ENDIF*) 
                        IF  p_pos <= patt.len
                        THEN
                            BEGIN
                            IF  (patt.k [p_pos] =
                                b_nptr.np_ptr^.nd_body [n_pos])
                                OR
                                (patt.k [p_pos] = csp_any1)
                            THEN
                                match := true
                            ELSE
                                IF  patt.k [p_pos] = csp_cclass
                                THEN
                                    match := bd05one_c_match
                                          (patt.k, p_pos,
                                          b_nptr.np_ptr^.nd_body[n_pos],
                                          patt_incr, true);
                                (*ENDIF*) 
                            (*ENDIF*) 
                            IF  match
                            THEN
                                BEGIN
                                p_pos  := p_pos + patt_incr;
                                n_pos  := n_pos + 1;
                                strpos := strpos + 1;
                                IF  shift
                                THEN
                                    BEGIN
                                    cl.ce_n_pos   := n_pos;
                                    cl.ce_strpos  := strpos;
                                    cl.ce_act_pno := act_pno;
                                    shift         := false
                                    END
                                (*ENDIF*) 
                                END
                            ELSE
                                IF  shift
                                THEN
                                    BEGIN
                                    IF  patt.k [p_pos] <> csp_star1
                                    THEN
                                        BEGIN
                                        n_pos  := n_pos + 1;
                                        strpos := strpos + 1
                                        END
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    IF  cl_index = 0
                                    THEN
                                        ok := false
                                    ELSE
                                        BEGIN
                                        strpos  := cl.ce_strpos;
                                        n_pos   := cl.ce_n_pos;
                                        p_pos   := cl.ce_p_pos;
                                        act_pno := cl.ce_act_pno;
                                        shift   := true;
                                        IF  act_pno <>
                                            b_nptr.np_ptr^.nd_id
                                        THEN
                                            BEGIN
                                            left :=b_nptr.np_ptr^.nd_id;
                                            b13r_release_node (b_nptr,
                                                  b_curr, lru_normal);
                                            IF  b_first
                                            THEN
                                                b_pno1 := act_pno
                                            ELSE
                                                b_pno2 := act_pno;
                                            (*ENDIF*) 
                                            bd13GetNode (b_curr, act_pno,
                                                  plmNoLock_ebd00,
                                                  nr_for_read, b_nptr);
                                            END
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                (*ENDIF*) 
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                UNTIL
                    (p_pos > patt.len) OR
                    (strpos > b_nstop) OR
                    (trError_gg00 <> e_ok  ) OR
                    NOT ok;
                (*ENDREPEAT*) 
                IF  p_pos > patt.len
                THEN
                    found := true;
                (*ENDIF*) 
                IF  (strpos > b_nstop + 1) OR NOT ok
                THEN
                    found := false
                (*ENDIF*) 
                END
            (*ENDIF*) 
        (*ENDIF*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
&ifdef TRACE
t01int4 (bd_byte, 'rpm res     ', ord (found));
&endif
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd05search_substring (VAR nptr : tbd_node_ptrs;
            npos             : tsp00_Int4;
            start_pos        : tsp00_Int4;
            stop_pos         : tsp00_Int4;
            VAR patt_info    : tbd05_pattern_info;
            VAR from_str_pos : tsp00_Int4;
            VAR to_str_pos   : tsp00_Int4;
            VAR current      : tbd_current_tree);
 
VAR
      found         : boolean;
      result        : tsp00_LcompResult;
      nnptr         : tbd_node_ptrs;
      incr_len      : tsp00_Int4;
      act_length    : tsp00_Int4;
      remain_length : tsp00_Int4;
      search_len    : tsp00_Int4;
      stoppos_sub   : tsp00_Int4;
      bstr_pos      : tsp00_Int4;
      left, next    : tsp00_PageNo;
      n_comp        : tbd05_bstr_comp;
 
BEGIN
WITH patt_info, current, curr_trans^ DO
    BEGIN
    found          := false;
    nnptr.np_ptr   := NIL;
    nnptr.np_cbptr := NIL;
    npos           := npos + BODY_BEG_BD00;
    from_str_pos   := start_pos;
    stoppos_sub    := stop_pos - pi_sublen + 1;
    next           := nptr.np_ptr^.nd_id;
    WITH n_comp DO
        BEGIN
        b_pno1  := next;
        b_pno2  := NIL_PAGE_NO_GG00;
        b_first := true
        END;
    (*ENDWITH*) 
    REPEAT
        IF  npos = MAX_BOTTOM_BD00
        THEN
            BEGIN
            next := nptr.np_ptr^.nd_right;
            left := nptr.np_ptr^.nd_id;
            b13r_release_node (nptr, current, lru_normal);
            IF  nnptr.np_ptr <> NIL
            THEN
                BEGIN
                WITH n_comp DO
                    BEGIN
                    b_pno1 := b_pno2;
                    b_pno2 := NIL_PAGE_NO_GG00
                    END;
                (*ENDWITH*) 
                nptr           := nnptr;
                nnptr.np_ptr   := NIL;
                nnptr.np_cbptr := NIL;
                next           := nptr.np_ptr^.nd_id
                END
            ELSE
                BEGIN
                n_comp.b_pno1 := next;
                bd13GetNode (current, next, plmNoLock_ebd00, nr_for_read, nptr);
                END;
            (*ENDIF*) 
            IF  trError_gg00 = e_ok
            THEN
                npos := BODY_BEG_BD00
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  (trError_gg00 = e_ok) AND
            (pi_with_pattern AND (pi_sublen = 0) AND (pi_subend = 0))
        THEN
            BEGIN
            WITH n_comp DO
                BEGIN
                b_nptr  := nptr;
                b_nstop := stop_pos;
                b_curr  := current
                END;
            (*ENDWITH*) 
            bstr_pos  := from_str_pos;
            bd05right_pattern_match (n_comp, npos, pi_pattern, 1,
                  bstr_pos, found, 0);
            nptr := n_comp.b_nptr;
            IF  found
            THEN
                BEGIN
                to_str_pos := bstr_pos - 1;
                bstr_pos   := from_str_pos
                END
            ELSE
                BEGIN
                npos         := npos + 1;
                from_str_pos := from_str_pos + 1
                END
            (*ENDIF*) 
            END
        ELSE
            IF  trError_gg00 = e_ok
            THEN
                BEGIN
                IF  (MAX_BOTTOM_BD00 - npos) >
                    (stoppos_sub - from_str_pos + 1)
                THEN
                    search_len := stoppos_sub - from_str_pos + 1
                ELSE
                    search_len := MAX_BOTTOM_BD00 - npos;
                (*ENDIF*) 
                IF  search_len > 0
                THEN
                    BEGIN
                    incr_len := s30lenl (nptr.np_ptr^,
                          pi_pattern.k [pi_subbeg], npos, search_len);
                    from_str_pos := from_str_pos + incr_len;
                    bstr_pos     := from_str_pos;
                    npos         := npos + incr_len;
&                   ifdef TRACE
                    t01int4 (bd_byte, 'new npos    ', npos);
&                   endif
                    IF  npos <> MAX_BOTTOM_BD00
                    THEN
                        BEGIN
                        IF  (npos + pi_sublen) <= MAX_BOTTOM_BD00
                        THEN
                            BEGIN
                            IF  nptr.np_ptr^.nd_body [npos + pi_sublen - 1] =
                                pi_pattern.k [pi_subend]
                            THEN
                                BEGIN
                                s30cmp (nptr.np_ptr^, npos, pi_sublen,
                                      pi_pattern.k, pi_subbeg,
                                      pi_sublen, result);
                                found := (result = l_equal)
                                END
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            IF  nnptr.np_ptr = NIL
                            THEN
                                BEGIN
                                n_comp.b_pno2 := nptr.np_ptr^.nd_right;
                                bd13GetNode (current, nptr.np_ptr^.nd_right,
                                      plmNoLock_ebd00, nr_for_read, nnptr);
                                END;
                            (*ENDIF*) 
                            IF  trError_gg00 = e_ok
                            THEN
                                BEGIN
                                act_length := MAX_BOTTOM_BD00 - npos;
                                remain_length := pi_sublen - act_length;
                                IF  nnptr.np_ptr^.nd_body [BODY_BEG_BD00+
                                    remain_length - 1]
                                    = pi_pattern.k [pi_subend]
                                THEN
                                    BEGIN
                                    s30cmp (nptr.np_ptr^, npos,
                                          act_length, pi_pattern.k,
                                          pi_subbeg, act_length,result);
                                    found := (result = l_equal);
                                    IF  found
                                    THEN
                                        BEGIN
                                        s30cmp (nnptr.np_ptr^,
                                              BODY_BEG_BD00,
                                              remain_length,
                                              pi_pattern.k,
                                              pi_subbeg + act_length,
                                              remain_length, result);
                                        found := (result = l_equal)
                                        END
                                    (*ENDIF*) 
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  (trError_gg00 = e_ok) AND found
                        THEN
                            BEGIN
                            IF  NOT pi_with_pattern
                            THEN
                                to_str_pos := from_str_pos +
                                      pi_sublen - 1
                            ELSE
                                BEGIN
                                bstr_pos := bstr_pos + pi_sublen;
                                IF  pi_subend < pi_pattern.len
                                THEN
                                    BEGIN
                                    n_comp.b_nstop := stop_pos;
                                    n_comp.b_curr  := current;
                                    IF  nnptr.np_ptr <> NIL
                                    THEN
                                        BEGIN
                                        WITH n_comp DO
                                            BEGIN
                                            b_first := false;
                                            b_nptr  := nnptr;
                                            bd05right_pattern_match (
                                                  n_comp, BODY_BEG_BD00 +
                                                  remain_length,
                                                  pi_pattern,
                                                  pi_subend + 1,
                                                  bstr_pos, found, 0);
                                            nnptr := b_nptr
                                            END;
                                        (*ENDWITH*) 
                                        IF  (nnptr.np_ptr^.nd_id
                                            <> nptr.np_ptr^.nd_right)
                                            AND
                                            (trError_gg00 = e_ok)
                                        THEN
                                            BEGIN
                                            left := nnptr.np_ptr^.nd_id;
                                            b13r_release_node (nnptr,
                                                  current, lru_normal);
                                            n_comp.b_pno1 :=
                                                  nptr.np_ptr^.nd_right;
                                            bd13GetNode (current, nptr.np_ptr^.nd_right,
                                                  plmNoLock_ebd00, nr_for_read, nnptr);
                                            END
                                        (*ENDIF*) 
                                        END
                                    ELSE
                                        BEGIN
                                        WITH n_comp DO
                                            BEGIN
                                            b_nptr  := nptr;
                                            b_first := true;
                                            bd05right_pattern_match (
                                                  n_comp,
                                                  npos + pi_sublen,
                                                  pi_pattern,
                                                  pi_subend + 1,
                                                  bstr_pos, found, 0);
                                            nptr := b_nptr
                                            END;
                                        (*ENDWITH*) 
                                        IF  (nptr.np_ptr^.nd_id <> next)
                                            AND
                                            (trError_gg00 = e_ok)
                                        THEN
                                            BEGIN
                                            left := nptr.np_ptr^.nd_id;
                                            b13r_release_node (nptr,
                                                  current, lru_normal);
                                            n_comp.b_pno1 := next;
                                            bd13GetNode (current, next,
                                                  plmNoLock_ebd00, nr_for_read, nptr);
                                            END
                                        (*ENDIF*) 
                                        END
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                IF  found AND (trError_gg00 = e_ok)
                                THEN
                                    BEGIN
                                    to_str_pos := bstr_pos - 1;
                                    bstr_pos   := from_str_pos;
                                    IF  pi_subbeg > 1
                                    THEN
                                        BEGIN
                                        bstr_pos := bstr_pos - 1;
                                        WITH n_comp DO
                                            BEGIN
                                            b_nptr    := nptr;
                                            b_first   := true;
                                            b_nstop   := start_pos;
                                            b_curr    := current;
&                                           ifdef TRACE
                                            t01int4 (bd_byte,
                                                  '=bstr_pos   ',
                                                  bstr_pos);
                                            t01int4 (bd_byte,
                                                  '=from_str_ps',
                                                  from_str_pos);
&                                           endif
                                            bd05left_pattern_match (
                                                  n_comp, npos - 1,
                                                  pi_pattern.k,
                                                  pi_subbeg - 1,
                                                  bstr_pos, found, 0);
                                            nptr := b_nptr;
&                                           ifdef TRACE
                                            t01int4 (bd_byte,
                                                  '=bstr_pos   ',
                                                  bstr_pos);
                                            t01int4 (bd_byte,
                                                  '=from_str_ps',
                                                  from_str_pos);
&                                           endif
                                            IF  (nptr.np_ptr^.nd_id
                                                <> next)
                                                AND
                                                (trError_gg00 = e_ok)
                                            THEN
                                                BEGIN
                                                left :=
                                                      nptr.np_ptr^.nd_id;
                                                b13r_release_node (nptr,
                                                      current,
                                                      lru_normal);
                                                b_pno1 := next;
                                                bd13GetNode (current, next,
                                                      plmNoLock_ebd00, nr_for_read, nptr);
                                                END;
                                            (*ENDIF*) 
                                            IF  trError_gg00 = e_ok
                                            THEN
                                                BEGIN
                                                bstr_pos := bstr_pos +1;
                                                IF  NOT found
                                                THEN
                                                    BEGIN
                                                    npos := npos + 1;
                                                    from_str_pos :=
                                                       from_str_pos + 1
                                                    END
                                                (*ENDIF*) 
                                                END
                                            (*ENDIF*) 
                                            END
                                        (*ENDWITH*) 
                                        END
                                    (*ENDIF*) 
                                    END
                                ELSE
                                    BEGIN
                                    npos         := npos + 1;
                                    from_str_pos := from_str_pos + 1
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            npos         := npos + 1;
                            from_str_pos := from_str_pos + 1
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
&           ifdef TRACE
            (*ENDIF*) 
        (*ENDIF*) 
        t01int4 (bd_byte, 'bstr_pos    ', bstr_pos);
        t01int4 (bd_byte, 'from_str_pos', from_str_pos);
&       endif
    UNTIL
        found OR (trError_gg00 <> e_ok) OR (bstr_pos >= stop_pos) OR
        ((from_str_pos + pi_sublen) > stop_pos);
    (*ENDREPEAT*) 
    END;
(*ENDWITH*) 
WITH current, curr_trans^ DO
    BEGIN
    IF  nptr.np_ptr <> NIL
    THEN
        b13r_release_node (nptr, current, lru_normal);
    (*ENDIF*) 
    IF  nnptr.np_ptr <> NIL
    THEN
        b13r_release_node (nnptr, current, lru_normal);
    (*ENDIF*) 
    IF  trError_gg00 = e_ok
    THEN
        IF  found
        THEN
            from_str_pos := bstr_pos
        ELSE
            BEGIN
            from_str_pos := cgg_eo_bytestr;
            to_str_pos   := cgg_eo_bytestr
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
