Author Topic: HLA vector and list function library ... also readLine and readWord ...  (Read 30316 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
This space is designated to hold a library of HLA vector and HLA list functions ... similar to the Cvec/Cvec2 and Clist/Clist2 library of functions available here...

http://developers-heaven.net/forum/index.php?topic=2580.0


For some example programs that demo the use of these HLA vector and list containers with their push_back, (and list push_front, and vector reserve) ... and merge sort, insert sort, find, erase, and unique functions ... see this next link ...

http://developers-heaven.net/forum/index.php?topic=2599.0
 

The first set of vector and list functions, permit just one type of vector or list in a program.  These pairs of include files are named:


The first pair is:

"vector_func's.hhf"
"vector.hhf"

If you include file "vector_func's.hhf" to get access to the sort, etc... functions, that file FIRSTLY includes file "vector.hhf", which firstly includes file "stdlib.hhf"




The next pair is:

"sllist_func's.hhf"
"sllist.hhf"


If you include file "sllist_func's.hhf" to get access to the sort, etc... functions, that file FIRSTLY includes file "sllist.hhf", which firstly includes file "stdlib.hhf"



Note: see the vector2/sllist2 .hhf files at the bottom also ... linked here ...

http://developers-heaven.net/forum/index.php?topic=2600.msg2978#msg2978
« Last Edit: September 09, 2012, 10:51:05 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #1 on: August 17, 2012, 02:56:23 AM »
The vector pair:

"vector.hhf"

Code: [Select]
// vector.hhf // 2012-08-21 //


#includeOnce( "stdlib.hhf" )


// NB!!! the record Rec must be defined before including this file
// ALSO  the type pRec: pointer to Rec;

// ALSO ... the procedure freeRec( pr: pRec );
/* // for example ... //
    procedure freeRec( pr: pRec in eax ); @nodisplay;
    begin freeRec;
        free( (type Rec [eax]).str );
    end freeRec;
*/

? @nodisplay:= true; // All procedures have @nodisplay 'as default' now.


#if( !@defined( InitCap ) )
const
    InitCap: uns32 := 8;
#endif

type   
    Vec:    record
                ary:        pRec;
                capacity:   uns32;
                size:       uns32;   
            endrecord;
 
 
procedure initVec( var v: Vec );
begin initVec;
    push( ebx );
    mov( v, ebx );
    mov( 0, (type Vec [ebx]).ary );
    mov( 0, (type Vec [ebx]).capacity );
    mov( 0, (type Vec [ebx]).size );
    pop( ebx );
end initVec;


// double capacity ...
procedure enlargeVec( var v: Vec );
begin enlargeVec;
    push( eax ); push( ebx ); push( ecx );
 
    mov( v, ebx );   
    if( (type Vec [ebx]).capacity != 0 ) then   // i.e. if capacity not zero
        shl( 1, (type Vec [ebx]).capacity );    // double capacity
    else;  // set initial capacity
        mov( mov( InitCap, eax ), (type Vec [ebx]).capacity );   
    endif;
   
    //mov( (type Vec [ebx]).elen, ecx );
    intmul( @size(Rec), (type Vec [ebx]).capacity, ecx );

    if( (type dword (type Vec [ebx]).ary) ) then mem.realloc( (type Vec [ebx]).ary, ecx );
    else mem.alloc( ecx );
    endif;
   
    mov( eax, (type Vec [ebx]).ary );

    pop( ecx ); pop( ebx ); pop( eax );
end enlargeVec;


// if size == capacity then enlarge ...
procedure push_backVec( var v: Vec; var r: Rec );
begin push_backVec;
    //push( ebx ); push( ecx ); push( esi ); push( edi ); // caller must preserve if needed
   
    // if size == capacity then enlarge/double capacity ...
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    if( ecx == (type Vec [ebx]).capacity ) then
        enlargeVec( (type Vec [ebx]) );
    endif;
   
   
    // ok ... now append (copy) of new rec ...
   
    mov( r, esi ); // get address of new Rec into esi ...
    //mov( (type Vec [ebx]).size, edi );
    intmul( @size(Rec), (type Vec [ebx]).size, edi );
    add( (type Vec [ebx]).ary, edi ); // get offset into edi

    // get num bytes to copy in ecx ...
    mov( @size(Rec), ecx );
    rep.movsb();
   
    inc( (type Vec [ebx]).size ); // update size
 
    //pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end push_backVec;


procedure reserveVec( var v: Vec; newCap: uns32  );
begin reserveVec;
    push( eax ); push( ebx );

    mov( newCap, eax );
    mov( v, ebx );
    if(  eax > (type Vec [ebx]).capacity ) then
   
        mov( eax, (type Vec [ebx]).capacity );
        intmul( @size(Rec), eax );          // num new bytes in eax
        if( (type dword (type Vec [ebx]).ary) ) then
            mem.realloc( (type Vec [ebx]).ary, eax );
        else
            mem.alloc( eax );
        endif;
        mov( eax, (type Vec [ebx]).ary );   // update new ary pointer
       
    endif;

    pop( ebx ); pop( eax );
end reserveVec;


procedure clearVec( var v: Vec );
begin clearVec;
    push( eax ); push( ebx ); push( ecx );
   
    mov( v, ebx );
    mov( (type Vec[ebx]).size, ecx );
    for( dec( ecx ); (type int32 ecx) >= 0; dec( ecx ) ) do
        intmul( @size(Rec), ecx, eax );
        add( (type Vec [ebx]).ary, eax );
        freeRec( eax ); // recall this procedure 'freeRec' must be defined
                        // along with type Rec, BEFORE including this file
    endfor;
   
    mem.free( (type Vec [ebx]).ary );
   
    initVec( (type Vec [ebx]) );
 
    pop( ecx ); pop( ebx ); pop( eax );
end clearVec;
« Last Edit: August 22, 2012, 03:40:19 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #2 on: August 17, 2012, 02:57:02 AM »
"vector_func's.hhf"

Code: [Select]
// vector_func's.hhf // 2012-08-21 //

#includeOnce ( "vector.hhf" )


type
    pVec: pointer to Vec;


#if( !@defined( pMyCmp ) )
static
    pMyCmp: procedure( a: dword in esi; b: dword in edi ); @returns( "eax" );
#endif

 

// re. isort ... note: cmp func is a < b
// re. msort ... note: cmp func is a <= b

procedure isortVec( var v: Vec );
static
    rcmp:   Rec;
    tmpReg: dword;
begin isortVec;
    push( eax ); push( ebx ); push( ecx );  push( edx ); push( esi ); push( edi );
   
     //int i, j; // i in eax, j in edx
    // start with an array of just the first 2 elements (if exists) ...
    // for( i = 1; i < cv->size; ++i )
    cld();
    mov( v, ebx );
    for( mov( 1, eax ); eax < (type Vec [ebx]).size; inc( eax ) ) do
   
        // update this cmp Rec on each outer loop
        //memcpy( &cmp, &cv->ary[i], sizeof(Rec) );
        mov( &rcmp, edi );
        intmul( @size(Rec), eax, esi );
        add( (type Vec [ebx]).ary, esi );
        mov( @size(Rec), ecx ); // get # bytes to copy in a Rec ... into ecx
        rep.movsb(); // ok ... got copy into rcmp ...
 
        // get index of element just to the left of the above 'cmp' to start comparisons
        mov( eax, edx );    // j = i
        dec( edx );         // --j // i.e. j = i-1; //
        while( (type int32 edx) >= 0 ) do   // while( j >= 0 && myCmp(&cmp, &cv->ary[j]) < 0 )
       
            intmul( @size(Rec), edx, edi ); // get offset into edi ..
            add( (type Vec [ebx]).ary, edi );
            mov( &rcmp, esi );
       
            //breakif( !pMyCmp(esi, edi) ); // 'copy up' // but first ...
            mov( eax, tmpReg ); // get copy of loop counter in eax
            pMyCmp( esi, edi );
            if( eax ) then
                mov( tmpReg, eax );
            else
                mov( tmpReg, eax );
                break;
            endif;
           
            // Now ...  'copy up' ...
            //memcpy( &cv->ary[j+1], &cv->ary[j], sizeof(Rec) );
            intmul( @size(Rec), edx, esi );
            add( (type Vec [ebx]).ary, esi );
            mov( esi, edi );
            add( @size(Rec), edi ); // to inc( j ) add size  //
            mov( @size(Rec), ecx ); // get # bytes to copy in a Rec into ecx
            rep.movsb();       
       
            dec( edx ); //--j; // --j to prepare for next inner loop
           
        endwhile;
       
        // insert pointer at index j+1 (since j was decremented above ...
        //memcpy( &cv->ary[j+1], &cmp, sizeof(Rec) );
        inc( edx ); // ++j
        mov( &rcmp, esi );
        intmul( @size(Rec), edx, edi );
        add( (type Vec [ebx]).ary, edi );
        mov( @size(Rec), ecx ); // get # bytes to copy in a Rec into ecx
        rep.movsb();
 
    endfor;
   
    pop( edi ); pop( esi ); pop( edx ); pop( ecx ); pop( ebx ); pop( eax );
end isortVec; // size hasn't changed ...



////////////////////////////////////////////////////////////////////////////
// re. msort ... note: cmp func is a <= b

procedure mergeVec( pv: pVec in ebx; bot: int32; top: int32; ptmp: pVec in edx );
var
    mid:    int32; // set to (bot+top)/2
    sz:     int32; // set to top-bot+1    // size of the range to be merged
    j:      int32;
    tmpReg: dword;
begin mergeVec;
    //push( eax ); push( ecx ); push( esi ); push( edi );
   
    //int mid = (bot+top)/2;
    mov( top, eax );
    add( bot, eax );
    shr( 1, eax ); // divide by 2
    mov( eax, mid );
    //int sz = top - bot + 1;   // size of the range to be merged
    mov( top, eax );
    sub( bot, eax );
    inc( eax );
    mov( eax, sz );   
    mov( 0, j );        // int j = 0;        // next open index in tmp
    mov( bot, eax );    // int h1 = bot;     // next index to consider in 1st half
    mov( mid, ecx );    // int h2 = mid + 1; // next index to consider in 2nd half
    inc( ecx );
   
    // while indexes h1 and h2 are not past their ends ...
    cld();
    while( eax <= mid && ecx <= top ) do // while( h1 <= mid && h2 <= top )
       
        // move the smaller element into the tmp vec 'next' ...
        // if( myCmp( &(cv->ary[h1]), &(cv->ary[h2]) ) <= 0  )
        intmul( @size(Rec), eax, esi );
        add( (type Vec [ebx]).ary, esi );
       
        intmul( @size(Rec), ecx, edi );
        add( (type Vec [ebx]).ary, edi );
       
        mov( eax, tmpReg );
        pMyCmp( esi, edi ); // if( myCmp(...) <= 0  )
       
        if( eax ) then // if( myCmp(...) <= 0 )
            //tmp->ary[j++] = cv->ary[h1++];
            mov( tmpReg, eax );                     // restore eax
            intmul( @size(Rec), eax, esi );
            add( (type Vec [ebx]).ary, esi );

            intmul( @size(Rec), j, edi );
            add( (type Vec [edx]).ary, edi );

            mov( ecx, tmpReg );
            mov( @size(Rec), ecx );
            rep.movsb(); // tmp->ary[j++] = cv->ary[h1++];
            mov( tmpReg, ecx );

            inc( eax ); // ++h1
            inc( j );

        else
            //tmp->ary[j++] = cv->ary[h2++];
            mov( tmpReg, eax );                     // restore eax

            intmul( @size(Rec), ecx, esi );         // ecx holds h2
            add( (type Vec [ebx]).ary, esi );

            intmul( @size(Rec), j, edi );
            add( (type Vec [edx]).ary, edi );

            mov( ecx, tmpReg );
            mov( @size(Rec), ecx );
            rep.movsb(); // tmp->ary[j++] = cv->ary[h2++];
            mov( tmpReg, ecx );

            inc( ecx ); // ++h2
            inc( j );
           
        endif;

    endwhile;

   
    // Note: only one (at most) of the two 'while's' below is executed ...
   
    //while( h1 <= mid ) // copy any remaining entries (1st half)
        //tmp->ary[j++] = cv->ary[h1++];
    while( eax <= mid ) do
       
        intmul( @size(Rec), eax, esi );
        add( (type Vec [ebx]).ary, esi );

        intmul( @size(Rec), j, edi );
        add( (type Vec [edx]).ary, edi );

        mov( ecx, tmpReg );
        mov( @size(Rec), ecx );
        rep.movsb(); // tmp->ary[j++] = cv->ary[h1++];
        mov( tmpReg, ecx );

        inc( eax ); // ++h1
        inc( j );
   
    endwhile;
           
         
    //while( h2 <= top ) // copy any remaining entries (2nd half)
        //tmp->ary[j++] = cv->ary[h2++];
       
    while( ecx <= top ) do 
     
        intmul( @size(Rec), ecx, esi );
        add( (type Vec [ebx]).ary, esi );

        intmul( @size(Rec), j, edi );
        add( (type Vec [edx]).ary, edi );

        mov( ecx, tmpReg );
        mov( @size(Rec), ecx );
        rep.movsb(); // tmp->ary[j++] = cv->ary[h2++];
        mov( tmpReg, ecx );

        inc( ecx ); // ++h2
        inc( j );
       
    endwhile;
         

    //for( j = 0; j < sz; ++j ) // copy back sorted tmp vec...
        //cv->ary[bot+j] = tmp->ary[j];
       
    mov( (type Vec [edx]).ary, esi );
    //mov( bot, edi );
    intmul( @size(Rec), bot, edi );
    add( (type Vec [ebx]).ary, edi );
    //mov( sz, ecx );
    intmul( @size(Rec), sz, ecx );
    rep.movsb();
   
    /*
    for( mov( 0, ecx ); ecx < sz; inc( ecx ) ) do

        intmul( @size(Rec), ecx, esi );
        add( (type Vec [edx]).ary, esi );
       
        mov( bot, eax );
        add( ecx, eax );
        intmul( @size(Rec), eax, edi );
        add( (type Vec [ebx]).ary, edi );
       
        mov( ecx, tmpReg );
        mov( @size(Rec), ecx );
        rep.movsb(); // cv->ary[bot+j] = tmp->ary[j];
        mov( tmpReg, ecx );
   
    endfor;
    */

    //pop( edi ); pop( esi ); pop( ecx ); pop( eax );
end mergeVec;


procedure my_msortVec( pv: pVec in ebx; bot: int32; top: int32; ptmp: pVec in edx );
var
    mid:    int32; 
begin my_msortVec;
    mov( top, eax );
    if( bot < eax ) then
   
        add( bot, eax );    // NOW EAX HOLDS top + bot
        shr( 1, eax );      // divide by 2 ...
        mov( eax, mid );    // mid = ( bot + top ) / 2;
       
        my_msortVec( ebx, bot, mid, edx );  // sort the first half ...
        inc( mid );                         // now mid = mid +1
       
        my_msortVec( ebx, mid, top, edx );  // and the second half
       
        mergeVec( ebx, bot, top, edx );     // now merge 2 sorted chunks
 
    endif;
end my_msortVec;


procedure msortVec( var v: Vec );
var
    Rega:   dword;
    Regb:   dword;
    Regc:   dword;
    Regd:   dword;
    Regesi: dword;
    Regedi: dword;
    tmp:    Vec;
begin msortVec;
    mov( eax, Rega ); mov( ebx, Regb ); mov( ecx, Regc ); mov( edx, Regd );
    mov( esi, Regesi ); mov( edi, Regedi );
   
    mov( v, ebx );
    mov( (type Vec [ebx]).size, eax );
    if( eax > 1 ) then
   
        initVec( tmp );
        reserveVec( tmp, eax ); // Note: resets cap... BUT tmp size still 0
        dec( eax );
        lea( edx, tmp );        // get address of new tmp Vec into edx ...
        my_msortVec( ebx, 0, eax, edx );
       
        // NOW done ... BUT only free ary mem that held copies of pointers
        mem.free( tmp.ary );
       
    endif;
   
    mov( Regedi, edi ); mov( Regesi, esi );
    mov( Regd, edx ); mov( Regc, ecx ); mov( Regb, ebx ); mov( Rega, eax );
   
end msortVec;



// returns index if string present, else -1 ...
procedure findVec( var v: Vec; var r: Rec ); @returns( "eax" );
begin findVec;
    push( ebx ); push( ecx ); push( esi ); push( edi );
   
    mov( v, ebx );
    for( mov( 0, ecx ); ecx < (type Vec [ebx]).size; inc( ecx ) ) do
        //if( myCmp(&cv->ary[i], r) == 0 )
        intmul( @size(Rec), ecx, esi );
        add( (type Vec [ebx]).ary, esi );
        mov( r, edi );
        pMyCmp( esi, edi ); // need an 'eq' cmp here ...
        breakif( eax );     // i.e. break if equal ...
    endfor;
   
    // now check loop end condition ...
    if( ecx != (type Vec [ebx]).size ) then
        mov( ecx, eax ); // found
    else
        mov( -1, eax ); // NOT found
    endif;
   
    pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end findVec;


// if int index valid, erases element there ...
procedure eraseVec( var v: Vec; index: uns32 in eax );
var
    tmpReg: dword;
begin eraseVec;
    push( ebx ); push( ecx ); push( esi ); push( edi );
   
    mov( v, ebx );
    if( (type int32 eax) >= 0 && (type int32 eax) < (type Vec [ebx]).size ) then
       
        mov( eax, tmpReg );
        intmul( @size(Rec), eax );
        add( (type Vec [ebx]).ary, eax );
        //freeVrec( &(cv->ary[index]) );
        freeRec( eax ); // must pass in eax, needed here if dynamic memory
        mov( tmpReg, eax  );
     

        //if( index < cv->size-1 )
            //memcpy(&cv->ary[index], &cv->ary[index+1], (cv->size-1-index)*sizeof(Rec));
       
        mov( (type Vec [ebx]).size, ecx );
        dec( ecx ); // ecx holds size-1
        if( eax < ecx ) then
            sub( eax, ecx ); // ecx now holds (cv->size-1-index)
            intmul( @size(Rec), ecx ); // ecx now holds bytes to copy ...
           
            intmul( @size(Rec), eax, edi );
            add( (type Vec [ebx]).ary, edi );
            mov( edi, esi );
            add( @size(Rec), esi );
            rep.movsb();
        endif;

        // now update size and return by reference (since address passed in)
        dec( (type Vec [ebx]).size );
           
    else
        mov( (type Vec [ebx]).size, ecx );
        dec( ecx ); // ecx holds size-1
        stdout.put( nl, "ERROR! Index ", index, " out of range 0..", (type int32 ecx), nl);
    endif;
   
    pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end eraseVec;




#if ( false )

// isort ///////////////////////////////////////////////////////////////////

void isortCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) )
{
    int i, j;
    Rec cmp;
    for( i = 1; i < cv->size; ++i ) /* start with an array of just the first 2 elements (if exists) */
    {
        memcpy( &cmp, &cv->ary[i], sizeof(Rec) ); /* get new cmp on each outer loop */
        j = i-1; /* get index of element just to the left of 'cmp' to start comparisons */
        while( j >= 0 && myCmp(&cmp, &cv->ary[j]) < 0 )
        {
            memcpy( &cv->ary[j+1], &cv->ary[j], sizeof(Rec) ); /* 'copy up' */
            --j; /* decrement j in preparation for next inner loop ... */
        }
        memcpy( &cv->ary[j+1], &cmp, sizeof(Rec) ); /* insert cmp at index j+1
                                                       (since j was decremented above) */
    }
    cv->isSorted = 1;
} /* size hasn't changed ... */


// msort ///////////////////////////////////////////////////////////////////

void mergeCvec( Cvec* cv, int bot, int top, Cvec* tmp,
            int (*myCmp) (const Rec* a, const Rec* b) )
{
    int mid = (bot+top)/2;
    int sz = top - bot + 1;   // size of the range to be merged
    int j = 0;                // next open index in tmp
    int h1 = bot;             // next index to consider in the 1st half
    int h2 = mid + 1;         // next index to consider in the 2nd half

    // while indexes h1 and h2 are not past their ends ...
    while( h1 <= mid && h2 <= top )
    {   // move the smaller element into the tmp vec next ...
        if( myCmp( &(cv->ary[h1]), &(cv->ary[h2]) ) <= 0  )
            tmp->ary[j++] = cv->ary[h1++];
        else
            tmp->ary[j++] = cv->ary[h2++];
    }
    // Note: only one of the two 'while's' below is executed ...
    while( h1 <= mid ) // copy any remaining entries (1st half)
        tmp->ary[j++] = cv->ary[h1++];
    while( h2 <= top ) // copy any remaining entries (2nd half)
        tmp->ary[j++] = cv->ary[h2++];

    for( j = 0; j < sz; ++j ) // copy back sorted tmp vec...
        cv->ary[bot+j] = tmp->ary[j];
}
void my_msortCvec( Cvec* cv, int bot, int top, Cvec* tmp,
               int (*myCmp) (const Rec* a, const Rec* b) )
{
    if( bot == top ) return;
    else
    {
        int mid = ( bot + top ) / 2;
        my_msortCvec( cv, bot, mid, tmp, myCmp );   // sort the first ...
        my_msortCvec( cv, mid+1, top, tmp, myCmp ); // and the second half
        mergeCvec( cv, bot, top, tmp, myCmp );      // now merge 2 sorted chunks
    }
}
/* *NOTE* Calling msortCvec sets the returned by ref Cvec to *** isSorted *** */
void msortCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) )
{
    if( cv->size > 1 )
    {
        Cvec tmp;
        initCvec( &tmp );
        reserveCvec( &tmp, cv->size ); /* Note: resets cap, BUT size still 0 */
        my_msortCvec( cv, 0, cv->size-1, &tmp, myCmp );
        cv->isSorted = 1;
        free( tmp.ary ); /* only free ary mem that held copies of pointers */
    }
}


// find ////////////////////////////////////////////////////////////////////

/* returns index if string present, else -1 */
int findCvec( Cvec* cv, const Rec* r, int (*myCmp) (const Rec* a, const Rec* b) )
{
    int i;
    for( i = 0; i < cv->size; ++i )
        if( myCmp(&cv->ary[i], r) == 0 ) return i;
    /* else if reach here ... */
    return -1;
}

// erase ///////////////////////////////////////////////////////////////////

/* if int index valid, erases element there */
void eraseCvec( Cvec* cv, int index )
{
    //int i;
    if( index < 0 || index >= cv->size )
        { printf( "\nERROR! Index %d out of range 0..%d\n", index, cv->size-1 );
          return; }

    freeVrec( &(cv->ary[index]) ); /* needed here for dynamic memory types */

    /* copy each (set of pointers above) down one index */
    //for( i = index; i < cv->size-1; ++i )
        //memcpy(&cv->ary[i], &cv->ary[i+1], sizeof(Rec));
    if( index < cv->size-1 )
        memcpy(&cv->ary[index], &cv->ary[index+1], (cv->size-1-index)*sizeof(Rec));

    /* now update size and return (by reference, since address passed in) */
    -- cv->size;
}

#endif
« Last Edit: August 22, 2012, 03:41:17 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #3 on: August 17, 2012, 02:59:23 AM »
The list pair:

"sllist.hhf"

Code: [Select]
// sllist.hhf // 2012-08-16 //

// using NNode to avoid conflict with Node
// using SLList to avoid conflict with List

#includeOnce( "stdlib.hhf" )


// NB!!! the record NNode must be defined before including this file
// ALSO  the type pNNode: pointer to NNode;


? @nodisplay:= true; // all procedures have @nodisplay 'as default' now


type   
    SLList: record
                head:   pNNode;
                tail:   pNNode;
                size:   uns32;   
            endrecord;
 
 
procedure initSLList( var lst: SLList );
begin initSLList;
    push( ebx );
    mov( lst, ebx );
    mov( 0, (type SLList [ebx]).head );
    mov( 0, (type SLList [ebx]).tail );
    mov( 0, (type SLList [ebx]).size );
    pop( ebx );
end initSLList;


procedure push_frontSLList( var lst: SLList; var n: NNode );
begin push_frontSLList;
    //push( ebx ); push( ecx ); push( esi ); push( edi ); // caller must preserve as needed
   
    cld();
    mem.alloc( @size(NNode) );
   
    mov( eax, edi );
    mov( n, esi ); // get address of new NNode into esi ...

    // get num bytes to copy in ecx ...
    mov( @size(NNode), ecx );
    rep.movsb();
   
    // ok ... now prepend (copy) of new NNode ...
    mov( lst, ebx );
    if( (type SLList [ebx]).size != 0 ) then // not empty
        mov( mov( (type SLList [ebx]).head, ecx ), (type NNode [eax]).next );
        mov( eax, (type SLList [ebx]).head );
    else
        mov( 0, (type NNode [eax]).next );
        mov( eax, (type SLList [ebx]).tail );
        mov( eax, (type SLList [ebx]).head );
    endif;
   
    inc( (type SLList [ebx]).size ); // update size
 
    //pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end push_frontSLList;

procedure push_backSLList( var lst: SLList; var n: NNode );
begin push_backSLList;
    // push( ebx ); push( ecx ); push( esi ); push( edi ); // caller must preserve as needed
   
    cld();
    mem.alloc( @size(NNode) );
   
    mov( eax, edi );
    mov( n, esi ); // get address of new NNode into esi ...

    // get num bytes to copy in ecx ...
    mov( @size(NNode), ecx );
    rep.movsb();
   
    mov( 0, (type NNode [eax]).next );
   
    // ok ... now append (copy) of new rec ...
    mov( lst, ebx );
    if( (type SLList [ebx]).size != 0 ) then // not empty
        mov( (type SLList [ebx]).tail, ecx );
        mov( eax, (type NNode [ecx]).next ); // now 'next' updated
        mov( eax, (type SLList [ebx]).tail );
    else
        mov( eax, (type SLList [ebx]).tail );
        mov( eax, (type SLList [ebx]).head );
    endif;
   
    inc( (type SLList [ebx]).size ); // update size
 
    // pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end push_backSLList;


procedure clearSLList( var v: SLList );
begin clearSLList;
    push( eax ); push( ebx ); push( ecx );
   
    mov( v, ebx );
    mov( (type SLList[ebx]).head, ecx );
    while(  ecx != 0 ) do
        mov( ecx, eax );
        mov( (type NNode [ecx]).next, ecx );
        freeNNode( eax ); // recall this procedure 'freeNNode' must be defined
                        // along with type NNode, BEFORE including this file
                       
        mem.free( eax );
    endwhile;
   
   
    initSLList( (type SLList [ebx]) );
 
    pop( ecx ); pop( ebx ); pop( eax );
end clearSLList;
« Last Edit: August 17, 2012, 03:22:00 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #4 on: August 17, 2012, 03:01:12 AM »
"sllist_func's.hhf"

Code: [Select]
// sllist_func's.hhf // // 2012-08-16 //


#includeOnce( "sllist.hhf" )


type
    pSLList: pointer to SLList;


#if( !@defined( pMyCmp ) )
static
    pMyCmp: procedure( a: dword in esi; b: dword in edi ); @returns( "eax" );
#endif


// re. isort ... note: cmp func is a <= b (for list, ALSO same as for msort)
// re. msort ... note: cmp func is a <= b


// pass in the address of the SLList and the new Node to insert ...
procedure insert_sortedSLList( var lst: SLList; pn: pNNode in eax );
//var
    //head: pNNode; // esi
var
    reg32:  dword;
begin insert_sortedSLList;
    push( ebx ); push( esi ); push( edi );
   
    //pList head;
    //if( !isSortedSLList( list, myCmp )) msortSLList( list, myCmp );
    //head = list->start;
    mov( lst, ebx );
    mov( (type SLList [ebx]).head, esi );
    mov( eax , edi );
   
    // firstly, we handle most common case where 'n' is NOT the first Node
    //if( head != NULL && myCmp( n, head ) >= 0 ) // NEED >=
    if( esi && pMyCmp( esi, edi ) ) then
        // so search the linked list for the right location
        //pList cur = head;
        //while( cur->next != NULL && myCmp( cur->next, n ) <= 0 )
        mov( esi, reg32 );
        mov( (type NNode [esi]).next, esi );
        //while( esi && pmyCmp( esi, edi ) ) do
        forever
            if( !esi || !pMyCmp( esi, edi ) ) then
                //cur = cur->next;
                mov( reg32, esi );
                break;
            else
                mov( esi, reg32 );
                mov( (type NNode [esi]).next, esi );
            endif;
        endfor;
       
        //if( cur == list->end ) list->end = n;
        if( esi == (type SLList [ebx]).tail ) then
            mov( edi, (type SLList [ebx]).tail );
        endif;
       
        //n->next = cur->next;
        mov( (type NNode [esi]).next, (type NNode [edi]).next );
       
        //cur->next = n;
        mov( edi, (type NNode [esi]).next );
       
        // list->start = head; // unchanged //
        //++ list->size;
        inc( (type SLList [ebx]).size );
    else // if we reach here, this IS the first node ...
        //n->next = head; // so set this node in first position
        mov( (type SLList [ebx]).head, (type NNode [edi]).next );
        //list->start = n;
        mov( edi, (type SLList [ebx]).head );
        //++ list->size;
        inc( (type SLList [ebx]).size );
        if( (type SLList [ebx]).size == 1 ) then
            // list->end = n;
            mov( edi, (type SLList [ebx]).tail );
        endif;
    endif;
   
    pop( edi ); pop( esi ); pop( ebx );
end insert_sortedSLList;

//void isortSLList( SLList* list, int (*myCmp) (const pList r1, const pList r2) )
procedure isortSLList( var lst: SLList );
var
    nSLList:    SLList;
    //cur:        pNNode; // eax
    //nextNode:   pNNode; // ecx
begin isortSLList;
    push( eax ); push( ebx ); push( ecx );
   
    initSLList( nSLList );
    mov( lst, ebx );
    //for( cur = list->start; cur != NULL; cur = nextNode )
    for( mov( (type SLList [ebx]).head, eax ); eax; mov( ecx, eax ) ) do
        //nextNode = cur->next; // get copy here before next is changed below
        mov( (type NNode [eax]).next, ecx );
        //insert_sortedSLList( &nSLList, cur, myCmp ); // 'cur' already is a Node pointer
        insert_sortedSLList( nSLList, eax );
    endfor;
     
    // now ... update old list with new front and back ...
    //list->start = nSLList.start;
    mov( nSLList.head, (type SLList [ebx]).head );
    //list->end = nSLList.end;
    mov( nSLList.tail, (type SLList [ebx]).tail );
   
    // size hasn't changed 

    pop( ecx ); pop( ebx ); pop( eax );
end isortSLList;


// merge two sorted SLLists with heads 'a' and 'b' ... in sorted order
procedure mergeSLLists(var a: SLList; var b: SLList ); @returns( "eax" ); // new head
var
    newMergedHead:  dword;
    //sorted:         dword; // use ebx // using edx now ..
begin mergeSLLists;
    //push( ebx ); push( esi ); push( edi ); // using edx instead of ebx here now

    //pList sorted, new_merged_head;
    mov( a, eax );
    mov( (type SLList [eax]).head, esi );
    mov( b, eax  );
    mov( (type SLList [eax]).head, edi );
   
    //if( a->start == NULL ) return b->start;
    //if( b->start == NULL ) return a->start;
    if( !esi ) then mov( edi, newMergedHead );
    elseif( !edi ) then mov( esi, newMergedHead );
   
    else
        //if( myCmp(a->start, b->start) <= 0 )
        if( pMyCmp( esi, edi ) ) then
            //sorted = a->start;
            //a->start = a->start->next;
            mov( esi, edx );
            mov( (type NNode [esi]).next, esi );
        else
            //sorted = b->start;
            //b->start = b->start->next;
            mov( edi, edx );
            mov( (type NNode [edi]).next, edi );
        endif;
       
        //new_merged_head = sorted;
        mov( edx, newMergedHead );

        // now ...
        //while( a->start != NULL && b->start != NULL )
        while( esi && edi ) do
            //if( myCmp(a->start, b->start) <= 0 )
            if( pMyCmp( esi, edi ) ) then
                //sorted->next = a->start;
                mov( esi, (type NNode [edx]).next );
                //sorted = a->start;
                mov( esi, edx );
                //a->start = a->start->next;
                mov( (type NNode [esi]).next, esi );   
            else
                //sorted->next = b->start;
                mov( edi, (type NNode [edx]).next );
                //sorted = b->start;
                mov( edi, edx );
                //b->start = b->start->next;
                mov( (type NNode [edi]).next, edi );
            endif;
        endwhile;

        // and finally ...
        //if( a->start != NULL )
        if( esi ) then
            //sorted->next = a->start;
            mov( esi, (type NNode [edx]).next );
        //else if( b->start != NULL )
        elseif( edi ) then
            //sorted->next = b->start;
            mov( edi, (type NNode [edx]).next );
        endif;
   
    endif;

    mov( newMergedHead, eax );
   
    //pop( edi ); pop( esi ); pop( ebx );
end mergeSLLists;


// a recursive mergesort ...
procedure mergesortSLList( var lst: SLList );
var
    // cur:    pNNode; // ecx
    a:      SLList;
    b:      SLList;
begin mergesortSLList;
    push( ebx );
    //push( ecx ); push( edx );
    //pList cur = list->start;
    mov( lst, ebx );
    mov( (type SLList [ebx]).head, ecx );
    mov( ecx, a.head );
    //SLList a, b;

    // base case is a SLList of length 0 or 1 ...
    //if ((cur == NULL) || (cur->next == NULL))  return;
   
    if( a.head != 0 /*&& b.head != 0*/ ) then
        mov( (type NNode [ecx]).next, b.head );
        if( b.head != 0 ) then
            // split SLList into 'a' and 'b' sublists ...
            //a.start = cur;
            //b.start = cur->next; // both these lines done above
            while( b.head != 0 /*&& ( b.start->next != NULL)*/  ) do
                mov( b.head, edx );
                mov( (type NNode [edx]).next, edx );
                breakif( !edx );
               
                //cur = cur->next;
                mov( (type NNode [ecx]).next, ecx );
                //b.start = b.start->next->next;
                mov( (type NNode [edx]).next, b.head );
            endwhile;

            //b.start = cur->next;
            mov( (type NNode [ecx]).next, b.head );
           
            //cur->next = NULL; // SLList divided into 2 roughly equal parts now
            mov( 0, (type NNode [ecx]).next );

            // recursively sort the sublists ...
            mergesortSLList( a );
            mergesortSLList( b );

            // merge the two sorted SLLists together ...
            //list->start = mergeSLLists(&a, &b, myCmp);
            mergeSLLists( a, b ); // returns new merged head in eax
            mov( eax, (type SLList [ebx]).head );
        endif;;
    endif;
    //pop( edx ); pop( ecx );
    pop( ebx );
end mergesortSLList;

 
procedure update_endSLList( var lst: SLList ); // after sort
begin update_endSLList;
    //push( ebx ); push( ecx );
   
    mov( lst, ebx );
    if( (type SLList [ebx]).size > 1 ) then
        //pList cur;
        //for( cur = list->start; cur->next != NULL; cur = cur->next ) ;
        //list->end = cur;
        //list->end->next = NULL; // this line NOT-needed/redundant
        mov( (type SLList [ebx]).head, ecx );
        while( (type NNode [ecx]).next != 0 ) do mov( (type NNode [ecx]).next, ecx ); endwhile;
        mov( ecx, (type SLList [ebx]).tail );
    endif;
   
    //pop( ecx ); pop( ebx );
end update_endSLList;


procedure msortSLList( var lst: SLList );
var
    Rega:   dword;
    Regb:   dword;
    Regc:   dword;
    Regd:   dword;
    Regesi: dword;
    Regedi: dword;
begin msortSLList;
    mov( eax, Rega ); mov( ebx, Regb ); mov( ecx, Regc ); mov( edx, Regd );
    mov( esi, Regesi ); mov( edi, Regedi );
   
    mov( lst, ebx );
    mergesortSLList( (type SLList [ebx]) );
    //mov( lst, ebx );
    update_endSLList( (type SLList [ebx]) );
   
    mov( Regedi, edi ); mov( Regesi, esi );
    mov( Regd, edx ); mov( Regc, ecx ); mov( Regb, ebx ); mov( Rega, eax );
end msortSLList;



// returns pointer if present, else returns 0
procedure findSLList( var lst: SLList; var nn: NNode ); @returns( "eax" );
begin findSLList;
    push( ebx ); push( esi ); push( edi );
   
   
    //pList p;
    mov( lst, ebx );
    mov( nn, edi );
    //for( p = cl->start; p != NULL; p = p->next )
    for( mov( (type SLList [ebx]).head, esi ); esi; mov( (type NNode [esi]).next, esi ) ) do
        //if( myCmp(p, pr) == 0 ) return p;
        pMyCmp( esi, edi ); // returns eax = 1 if found, else 0
        if( eax ) then
            mov( esi, eax );
            break;
        endif;
    endfor;
    // if not found above, eax is already 0
   
    pop( edi ); push( esi ); push( ebx );
end findSLList;


procedure eraseSLList( var lst: SLList;  pn: pNNode in eax ); // if pn valid, erase element there
//var
    //prev:   pNNode; // use edx
begin eraseSLList;
    push( ebx ); push( ecx ); push( edx );
   
    //pList prev = NULL, cur = cl->start;
    mov( 0, edx );
    mov( lst, ebx );
   
    for( mov( (type SLList [ebx]).head, ecx ); ecx && ecx != eax; mov( (type NNode [ecx]).next, ecx ) ) do
        //prev = cur;
        mov( ecx, edx );
    endfor;
   
    if( ecx ) then
       
        if( edx ) then // case of NOT FIRST element
            //prev->next = cur->next;
            mov( (type NNode [ecx]).next, (type NNode [edx]).next );
        else // case of IS FIRST element
            //cl->start = cl->start->next;
            mov( (type NNode [ecx]).next, (type SLList [ebx]).head );
        endif;
       
        //if( cur == cl->end ) cl->end = prev; /* case of IS LAST element*/
        if( ecx == (type SLList [ebx]).tail ) then
            mov( edx, (type SLList [ebx]).tail );
        endif;

        freeNNode( ecx ); // needed here for types like dynamic C strings, etc
        mem.free( ecx ); // free memory for dynamic Node ...

        // now update size and return (by reference, since address passed in)
        //-- cl->size;
        dec(  (type SLList [ebx]).size );
       
    else
        stdout.puts( nl "eraseSLList ERROR! Pointer NOT found ..." );
    endif;
   
    pop( edx ); pop( ecx ); pop( ebx );
end eraseSLList;



#if( !@defined( chrIsInStr ) )
    // returns *POSITION*  1..n  (POS = INDEX+1)  or  0 if NOT found //
    procedure chrIsInStr( c: char in al; s: string ); @returns( "eax" );
    begin chrIsInStr;
        str.chpos( s, al );
        inc( eax );
    end chrIsInStr;
#endif


procedure splitSLList( var sll: SLList; s: string; delims: string );
var
    myNNode:    NNode;
    reg32:      dword;
    i:          uns32;
begin splitSLList;
    push( eax ); push( ebx ); push( ecx ); push( edx );
   
    mov( sll, ebx );
    mov( s, ecx ); // ecx holds start address ...
   
    forever
   
        while( chrIsInStr( (type char [ecx]), delims ) ) do
            inc( ecx );
        endwhile;
       
        breakif( (type char [ecx]) == 0 ); // since 'empty' string
       
        mov( ecx, edx );
        inc( edx ); // edx holds address one past end of 'word' ...
       
        mov( (type char [edx]), al );
        while( al && !chrIsInStr( al, delims ) ) do
            inc( edx );
            mov( (type char [edx]), al );
        endwhile;
       
        mov( edx, reg32 );  // save a copy of 'end' in reg32 ...
        sub( ecx, edx );    // edx holds 'len of next word'
       
        mov( ecx, i );
        mov( s, eax );
        sub( eax, i );      // i is index to start
       
        str.a_substr( s, i, edx ); // start, len
        mov( eax, myNNode.nval );
       
        push_backSLList( (type SLList [ebx]), myNNode );
       
        mov( reg32, ecx );  // update (next) start pointer ecx ...
   
    endfor;
 
    pop( edx ); pop( ecx ); pop( ebx ); pop( eax );
end splitSLList;


procedure uniqueSLList( var lst: SLList );
begin uniqueSLList;
    push( eax ); push( ebx ); push( esi ); push( edi );

    //pList p = c->start;
    mov( lst, ebx );
    mov( (type SLList [ebx]).head, esi ); // esi holds cur NNode address
   
    if( esi ) then
        //while( p->next != NULL )
        while( (type NNode [esi]).next != 0 ) do
            //if( myCmp(p, p->next) == 0 )
            mov( (type NNode [esi]).next, edi );
            if( pMyCmp( esi, edi ) ) then // if equal then ...
                //pList tmp = p->next;
                mov( edi, eax ); // eax is tmp copy ...
               
                //p->next = p->next->next;
                mov( (type NNode [edi]).next, edi ); // now advance edi ...
                mov( edi, (type NNode [esi]).next );
               
                freeNNode( eax ); // needed here for types like dynamic Cstrings, etc
                mem.free( eax );
                //-- c->size;
                dec( (type SLList [ebx]).size );
            else
                //p = p->next;
                mov( edi, esi ); // mov esi up since not equal ...
            endif;
        endwhile;
   
        update_endSLList( (type SLList [ebx]) ) ; // update end ...
    endif;
   
    pop( edi ); pop( esi ); pop( ebx ); pop( eax );
end uniqueSLList;
« Last Edit: August 21, 2012, 08:28:29 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #5 on: August 17, 2012, 03:10:09 AM »
Now the FILE read functions, that permit reading in an HLA string of any length, restricted only by the amount of remaining available memory ...

These include files are named:

"readLine.hhf"

Called like this: (similar to getline in C++)

while( readLine( fin, lineStr ) ) do

   // process lineStr

endwhile;

and

"readWord.hhf"

Called like this:

while( readWord( fin, wordStr, delimitersStr ) ) do

   // process wordStr

endwhile;

Code: [Select]
// readLine.hhf // 2012-08-11 //

#includeOnce( "stdlib.hhf" )

#if( !@defined( InitStrCap ) )
const
    InitStrCap: uns32 := 1024;
#endif


// expects an unitialized string to be passed in ...
procedure readLine( fin:dword; var line:string ); @nodisplay; @returns("eax");
var
    cap:    dword;
    sTmp:   string;
   
begin readLine;
    push( ebx ); push( ecx );
   
    mov( InitStrCap, eax );
    mov( eax, cap );
    str.alloc( eax );
    mov( eax, ebx );
   
    mov( 0, ecx );      // and ... ecx tracks size
    if( !fileio.eof( fin ) ) then

        while( !fileio.eof( fin ) ) do
       
            fileio.getc( fin );
           
            if( al == stdio.cr ) then // Windows #13 #10
                fileio.getc( fin );
                break; // eat #10
            elseif( al == stdio.eoln ) then // Linux, etc ?
                break;
            endif;
           
            if( ecx == cap ) then   // size == cap, so realloc into cap x2 memory
                shl( 1, cap );      // cap gets x2 (doubled)...
                mov( ecx, (type str.strRec [ebx]).length );
                mov( 0, (type char [ebx+ecx+1]) );
                push( eax );        // preserve char in al ...
                str.realloc( ebx, cap );
                mov( eax, ebx );    // Ok ... now NEW string in ebx ..
                pop( eax );         // restore char in al in eax
            endif;
           
            mov( al, [ebx + ecx] );
            inc( ecx );
 
        endwhile;
       
        mov( ecx, (type str.strRec [ebx]).length );
        mov( 0, (type char [ebx+ecx]) );
       
        mov( ebx, sTmp );   // get a copy of address ...
        str.a_cpy( ebx );   // new 'right sized' string now in eax
       
        mov( line, ebx );
        mov( eax, [ebx] );  // so can return by ref new string
        str.free( sTmp );
    else
        str.free( ebx );    // prevent 'memory leak'
        mov( 0, eax );      // AT eof NOW, so return 'zero'
    endif;

    pop( ecx ); pop( ebx );
end readLine;


And ...

Code: [Select]
// readLineConsole.hhf // 2012-08-22  //

#includeOnce( "stdlib.hhf" )

#if( !@defined( InitCap ) )
const
    InitCap: uns32 := 256;
#endif

procedure readLineConsole; @nodisplay; @returns( "eax" );
var
    cap:    uns32;
begin readLineConsole;
    push( ebx ); push( ecx );
 
    mov( 0, ecx );      // ecx tracks size ...
    mov( ecx, cap );
    forever
       
        if( ecx == cap ) then
            if( ecx != 0 ) then
                shl( 1, cap ); // double cap
                str.realloc( ebx, cap );
            else
                mov( InitCap, cap );
                str.alloc( cap );
            endif;
            mov( eax, ebx );
        endif;
       
        stdin.getc();
        breakif( al == stdio.eoln );
       
        mov( al, [ebx+ecx] );
        inc( ecx );
       
    endfor;
   
    mov( 0, (type byte [ebx+ecx]) );            // 0 terminate
    mov( ecx, (type str.strRec [ebx]).length ); // update size

    str.a_cpy( ebx );   // returns 'right size capacity' string in eax ...
    str.free( ebx );    // can eliminate this 'tmp' string now ...
   
    pop( ecx ); pop( ebx );
end readLineConsole;
« Last Edit: August 27, 2012, 03:44:07 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #6 on: August 17, 2012, 03:12:40 AM »
"readWord.hhf"

Code: [Select]
// readWord.hhf // 2012-08-11 //

#includeOnce( "stdlib.hhf" )

#if( !@defined( InitStrCap ) )
const
    InitStrCap: uns32 := 32;
#endif

/*
#if( !@defined( chrIsInStr ) ) 
    // returns *POSITION*  1..n  (POS = INDEX+1)  or  0 if NOT found //
    procedure chrIsInStr( c: char in al; s: string ); @returns( "eax" );
    begin chrIsInStr;
        str.chpos( s, al );
        inc( eax );
    end chrIsInStr;
#endif
*/

// expects an unitialized string to be passed in ...
procedure readWord( fin:dword; var line:string; delims: string ); @nodisplay; @returns("eax");
var
    cap:    dword;
    sTmp:   string;
    c:      char;
begin readWord;
    push( ebx ); push( ecx );
   
    mov( 0, ecx );      // using ecx to track size ...
    mov( InitStrCap, eax );
    mov( eax, cap );
   
    str.alloc( eax );
    mov( eax, ebx );
   
    // firstly ... skip over any leading delimit char's ...
    while( !fileio.eof( fin ) ) do
        fileio.getc( fin );
        mov( al, c );
        //breakif( !chrIsInStr( al, delims ) );
        str.chpos( delims, al );
        if( eax == -1 ) then
            // ok ... we have a good char in c ...
            mov( c, al ); // restore good char value to al ...
            mov( al, [ebx + ecx] );
            inc( ecx );
            break;
        endif;
    endwhile;
   
    // now ... get rest of word ... (if any)
    while( !fileio.eof( fin ) ) do
       
        fileio.getc( fin );
        mov( al, c );
       
        //breakif( chrIsInStr( al, delims ) );
        str.chpos( delims, al );
        breakif( eax != -1 );
       
        if( ecx == cap ) then   // size == cap, so realloc into cap x2 memory
            shl( 1, cap );      // cap gets x2 (doubled)...
            mov( ecx, (type str.strRec [ebx]).length );
            mov( 0, (type char [ebx+ecx+1]) );
            str.realloc( ebx, cap );
            mov( eax, ebx );    // Ok ... now NEW string in ebx ..
        endif;
           
        mov( c, al ); // restore good char value to al ...
        mov( al, [ebx + ecx] );
        inc( ecx );
       
    endwhile;
   
    if( !ecx && fileio.eof( fin ) ) then // if eof and empty line ...
        str.free( ebx );
        mov( 0, eax );
    else
        mov( ecx, (type str.strRec [ebx]).length );
        mov( 0, (type char [ebx+ecx]) );
       
        mov( ebx, sTmp );   // get a copy of address ...
        str.a_cpy( ebx );   // new 'right sized' string now in eax
       
        mov( line, ebx );
        mov( eax, [ebx] );  // so can return by ref new string
        str.free( sTmp );
    endif;

    pop( ecx ); pop( ebx );
end readWord;


And ...

Code: [Select]
// readWordConsole.hhf // 2012-08-27 //

#includeOnce( "stdlib.hhf" )

#if( !@defined( InitStrCap ) )
const
    InitStrCap: uns32 := 32;
#endif

/*
#if( !@defined( chrIsInStr ) ) 
    // returns *POSITION*  1..n  (POS = INDEX+1)  or  0 if NOT found //
    procedure chrIsInStr( c: char in al; s: string ); @returns( "eax" );
    begin chrIsInStr;
        str.chpos( s, al );
        inc( eax );
    end chrIsInStr;
#endif
*/

// expects an unitialized string to be passed in ...
procedure readWordConsole( var line:string; delims: string ); @nodisplay; @returns("eax");
var
    cap:    dword;
    sTmp:   string;
    c:      char;
begin readWordConsole;
    push( ebx ); push( ecx );
   
    mov( 0, ecx );      // using ecx to track size ...
    mov( InitStrCap, eax );
    mov( eax, cap );
   
    str.alloc( eax );
    mov( eax, ebx );
   
    // firstly ... skip over any leading delimit char's ...
    forever
        stdin.getc();
        mov( al, c );
        if( al != stdio.eoln ) then
            str.chpos( delims, al );
            if( eax == -1 ) then
                // ok ... we have a good char in c ...
                mov( c, al ); // restore good char value to al ...
                mov( al, [ebx + ecx] );
                inc( ecx );
                break;
            endif;
        endif;
    endfor;
   
    // now ... get rest of word ... (if any)
    forever
       
        stdin.getc();
        breakif( al == stdio.eoln );
        mov( al, c );
       
        str.chpos( delims, al );
        breakif( eax != -1 );
       
        if( ecx == cap ) then   // size == cap, so realloc into cap x2 memory
            shl( 1, cap );      // cap gets x2 (doubled)...
            mov( ecx, (type str.strRec [ebx]).length );
            mov( 0, (type char [ebx+ecx+1]) );
            str.realloc( ebx, cap );
            mov( eax, ebx );    // Ok ... now NEW string in ebx ..
        endif;
           
        mov( c, al ); // restore good char value to al ...
        mov( al, [ebx + ecx] );
        inc( ecx );
       
    endfor;

    mov( ecx, (type str.strRec [ebx]).length );
    mov( 0, (type char [ebx+ecx]) );
   
    mov( ebx, sTmp );   // get a copy of address ...
    str.a_cpy( ebx );   // new 'right sized' string now in eax
   
    mov( line, ebx );
    mov( eax, [ebx] );  // so can return by ref new string
    str.free( sTmp );

    pop( ecx ); pop( ebx );
end readWordConsole;
« Last Edit: August 29, 2012, 06:24:03 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #7 on: August 17, 2012, 03:16:00 AM »
This second set of vector and list functions, permit any number of types of vector or list in a program.  These pairs of include files are named:


The first pair is:

"vector2_func's.hhf"
"vector2.hhf"

If you include file "vector2_func's.hhf" to get access to the sort, etc... functions, that file FIRSTLY includes file "vector2.hhf", which firstly includes file "stdlib.hhf"




The next pair is:

"sllist2_func's.hhf"
"sllist2.hhf"


If you include file "sllist2_func's.hhf" to get access to the sort, etc... functions, that file FIRSTLY includes file "sllist2.hhf", which firstly includes file "stdlib.hhf"
« Last Edit: August 21, 2012, 08:29:42 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #8 on: August 17, 2012, 03:17:52 AM »
The vector2 pair:

"vector2.hhf"

Code: [Select]
// vector2.hhf // 2012-08-15 //

#includeOnce( "stdlib.hhf" )

? @nodisplay:= true; // All procedures have @nodisplay 'as default' now.


#if( !@defined( InitCap ) )
const
    InitCap: uns32 := 8;
#endif

// Recall needs a procedure like freeRec( pr: dword in eax );
// so can pass proc address to pFreeRec used below ...
/* // for example ... //
    procedure freeRec( pr: dword in eax ); @nodisplay; @noframes;
    begin freeRec;
        free( (type Rec eax).str );
        ret();
    end freeRec;
*/

// get a (static) procedure pointer
static
    pFreeRec: procedure( a: dword in eax );
   
type   
    Vec:    record
                ary:        dword;
                capacity:   uns32;
                size:       uns32;
                elen:       uns32;
            endrecord;
 
 
procedure initVec( var v: Vec; eln: uns32 );
begin initVec;
    push( ebx );
    mov( v, ebx );
    mov( 0, (type Vec [ebx]).ary );
    mov( 0, (type Vec [ebx]).capacity );
    mov( 0, (type Vec [ebx]).size );
    mov( eln, (type Vec [ebx]).elen );
    pop( ebx );
end initVec;


// double capacity ...
procedure enlargeVec( var v: Vec );
begin enlargeVec;
    push( eax ); push( ebx ); push( ecx );
 
    mov( v, ebx );   
    if( (type Vec [ebx]).capacity != 0 ) then   // i.e. if capacity not zero
        shl( 1, (type Vec [ebx]).capacity );    // double capacity
    else;  // set initial capacity
        mov( mov( InitCap, eax ), (type Vec [ebx]).capacity );   
    endif;
   
    mov( (type Vec [ebx]).elen, ecx );
    intmul( (type Vec [ebx]).capacity, ecx );

    if( (type Vec [ebx]).ary ) then mem.realloc( (type Vec [ebx]).ary, ecx );
    else mem.alloc( ecx );
    endif;
   
    mov( eax, (type Vec [ebx]).ary );

    pop( ecx ); pop( ebx ); pop( eax );
end enlargeVec;


 // if size == capacity then enlarge ...
procedure push_backVec( var v: Vec; pr: dword );
begin push_backVec;
    //push( ebx ); push( ecx ); push( esi ); push( edi ); // caller must preserve if needed
   
    // if size == capacity then enlarge/double capacity ...
    mov( v, ebx );
    mov( (type Vec [ebx]).size, ecx );
    if( ecx == (type Vec [ebx]).capacity ) then
        enlargeVec( (type Vec [ebx]) );
    endif;
   
   
    // ok ... now append (copy) of new rec ...
   
    mov( pr, esi ); // get address of new Rec into esi ...
    mov( (type Vec [ebx]).size, edi );
    intmul( (type Vec [ebx]).elen, edi );
    add( (type Vec [ebx]).ary, edi ); // get offset into edi

    // get num bytes to copy in ecx ...
    mov( (type Vec [ebx]).elen,  ecx );
    rep.movsb();
   
    inc( (type Vec [ebx]).size ); // update size
 
    //pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end push_backVec;


procedure reserveVec( var v: Vec; newCap: uns32  );
begin reserveVec;
    push( eax ); push( ebx );

    mov( newCap, eax );
    mov( v, ebx );
    if(  eax > (type Vec [ebx]).capacity ) then
   
        mov( eax, (type Vec [ebx]).capacity );
        intmul( (type Vec [ebx]).elen, eax );       // num new bytes in eax
        if( (type Vec [ebx]).ary ) then
            mem.realloc( (type Vec [ebx]).ary, eax );
        else
            mem.alloc( eax );
        endif;
        mov( eax, (type Vec [ebx]).ary );           // update new ary pointer
       
    endif;

    pop( ebx ); pop( eax );
end reserveVec;


procedure clearVec( var v: Vec );
static
    rsize: uns32;
begin clearVec;
    push( eax ); push( ebx ); push( ecx );
   
    mov( v, ebx );
    mov( (type Vec [ebx]).elen, rsize );
    mov( (type Vec[ebx]).size, ecx );
    if( (type Vec [ebx]).ary ) then // if was allocated some memory ...
   
        for( dec( ecx ); (type int32 ecx) >= 0; dec( ecx ) ) do
            mov( ecx, eax );
            intmul( rsize, eax );
            add( (type Vec [ebx]).ary, eax );
            pFreeRec( eax ); // recall some procedure 'freeRec' must be defined
                            // along with some type Rec, BEFORE including this file
        endfor;
        mem.free( (type Vec [ebx]).ary );
       
    endif;
   
   
   
    initVec( (type Vec [ebx]), 0 );
 
    pop( ecx ); pop( ebx ); pop( eax );
end clearVec;
« Last Edit: August 17, 2012, 03:25:26 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #9 on: August 17, 2012, 03:19:59 AM »
"vector2_func's.hhf"

Code: [Select]
// vector2_func's.hhf // 2012-08-15 //

#includeOnce ( "vector2.hhf" )


type
    pVec: pointer to Vec;


#if( !@defined( pMyCmp ) )
static
    pMyCmp: procedure( a: dword in esi; b: dword in edi ); @returns( "eax" );
#endif



// re. isort ... note: cmp func is a < b (for vector)
// re. msort ... note: cmp func is a <= b

procedure isortVec( var v: Vec );
static
    tmpReg: dword;
var
    rsize:  uns32;
    prcmp:  dword;
begin isortVec;
    push( eax ); push( ebx ); push( ecx ); push( edx ); push( esi ); push( edi );
   
     //int i, j; // i in eax, j in edx
    // start with an array of just the first 2 elements (if exists) ...
    // for( i = 1; i < cv->size; ++i )
    cld();
    mov( v, ebx );
    mov( (type Vec [ebx]).elen, rsize );
    mem.alloc( rsize );
    mov( eax, prcmp );
    for( mov( 1, eax ); eax < (type Vec [ebx]).size; inc( eax ) ) do
   
        // update this cmp Rec on each outer loop
        //memcpy( &cmp, &cv->ary[i], sizeof(Rec) );
        mov( prcmp, edi );
        mov( eax, esi );
        intmul( rsize, esi );
        add( (type Vec [ebx]).ary, esi );
        mov( rsize, ecx ); // get # bytes to copy in a Rec ... into ecx
        rep.movsb(); // ok ... got copy into rcmp ...
 
        // get index of element just to the left of the above 'cmp' to start comparisons
        mov( eax, edx );    // j = i
        dec( edx );         // --j // i.e. j = i-1; //
        while( (type int32 edx) >= 0 ) do   // while( j >= 0 && myCmp(&cmp, &cv->ary[j]) < 0 )
       
            mov( edx, edi );
            intmul( rsize, edi ); // get offset into edi ..
            add( (type Vec [ebx]).ary, edi );
            mov( prcmp, esi );
       
            //breakif( !pMyCmp(esi, edi) ); // 'copy up' // but first ...
            mov( eax, tmpReg ); // get copy of loop counter in eax
            pMyCmp( esi, edi );
            if( eax ) then
                mov( tmpReg, eax );
            else
                mov( tmpReg, eax );
                break;
            endif;
           
            // Now ...  'copy up' ...
            //memcpy( &cv->ary[j+1], &cv->ary[j], sizeof(Rec) );
            mov( edx, esi );
            intmul( rsize, esi );
            add( (type Vec [ebx]).ary, esi );
            mov( esi, edi );
            add( rsize, edi ); // to inc( j ) add size  //
            mov( rsize, ecx ); // get # bytes to copy in a Rec into ecx
            rep.movsb();       
       
            dec( edx ); //--j; // --j to prepare for next inner loop
           
        endwhile;
       
        // insert pointer at index j+1 (since j was decremented above ...
        //memcpy( &cv->ary[j+1], &cmp, sizeof(Rec) );
        inc( edx ); // ++j
        mov( prcmp, esi );
        mov( edx, edi );
        intmul( rsize, edi );
        add( (type Vec [ebx]).ary, edi );
        mov( rsize, ecx ); // get # bytes to copy in a Rec into ecx
        rep.movsb();
 
    endfor;
   
    pop( edi ); pop( esi ); pop( edx ); pop( ecx ); pop( ebx ); pop( eax );
end isortVec; // size hasn't changed ...



////////////////////////////////////////////////////////////////////////////
// re. msort ... note: cmp func is a <= b

procedure mergeVec( pv: pVec in ebx; bot: int32; top: int32; ptmp: pVec in edx );
var
    mid:    int32; // set to (bot+top)/2
    sz:     int32; // set to top-bot+1    // size of the range to be merged
    j:      int32;
    tmpReg: dword;
    rsize:  uns32;
begin mergeVec;
    //push( eax ); push( ecx ); push( esi ); push( edi ); // NOTE: all 6 reg's preserved by msortVec
   
    //int mid = (bot+top)/2;
    mov( top, eax );
    add( bot, eax );
    shr( 1, eax ); // divide by 2
    mov( eax, mid );
    //int sz = top - bot + 1;   // size of the range to be merged
    mov( top, eax );
    sub( bot, eax );
    inc( eax );
    mov( eax, sz );   
    mov( 0, j );        // int j = 0;        // next open index in tmp
    mov( bot, eax );    // int h1 = bot;     // next index to consider in 1st half
    mov( mid, ecx );    // int h2 = mid + 1; // next index to consider in 2nd half
    inc( ecx );
   
    mov( (type Vec [ebx]).elen, rsize );
   
    // while indexes h1 and h2 are not past their ends ...
    cld();
    while( eax <= mid && ecx <= top ) do // while( h1 <= mid && h2 <= top )
       
        // move the smaller element into the tmp vec 'next' ...
        // if( myCmp( &(cv->ary[h1]), &(cv->ary[h2]) ) <= 0  )
        mov( eax, esi );
        intmul( rsize, esi );
        add( (type Vec [ebx]).ary, esi );
       
        mov( ecx, edi );
        intmul( rsize, edi );
        add( (type Vec [ebx]).ary, edi );
       
        mov( eax, tmpReg );
        pMyCmp( esi, edi ); // if( myCmp(...) <= 0  )
       
        if( eax ) then // if( myCmp(...) <= 0 )
            //tmp->ary[j++] = cv->ary[h1++];
            mov( tmpReg, eax );                     // restore eax
            mov( eax, esi );
            intmul( rsize, esi );
            add( (type Vec [ebx]).ary, esi );

            mov( j, edi );
            intmul( rsize, edi );
            add( (type Vec [edx]).ary, edi );

            mov( ecx, tmpReg );
            mov( rsize, ecx );
            rep.movsb(); // tmp->ary[j++] = cv->ary[h1++];
            mov( tmpReg, ecx );

            inc( eax ); // ++h1
            inc( j );

        else
            //tmp->ary[j++] = cv->ary[h2++];
            mov( tmpReg, eax );                     // restore eax

            mov( ecx, esi );
            intmul( rsize, esi );         // ecx holds h2
            add( (type Vec [ebx]).ary, esi );

            mov( j, edi );
            intmul( rsize, edi );
            add( (type Vec [edx]).ary, edi );

            mov( ecx, tmpReg );
            mov( rsize, ecx );
            rep.movsb(); // tmp->ary[j++] = cv->ary[h2++];
            mov( tmpReg, ecx );

            inc( ecx ); // ++h2
            inc( j );
           
        endif;

    endwhile;

   
    // Note: only one (at most) of the two 'while's' below is executed ...
   
    //while( h1 <= mid ) // copy any remaining entries (1st half)
        //tmp->ary[j++] = cv->ary[h1++];
    while( eax <= mid ) do
       
        mov( eax, esi );
        intmul( rsize, esi );
        add( (type Vec [ebx]).ary, esi );

        mov( j, edi );
        intmul( rsize, edi );
        add( (type Vec [edx]).ary, edi );

        mov( ecx, tmpReg );
        mov( rsize, ecx );
        rep.movsb(); // tmp->ary[j++] = cv->ary[h1++];
        mov( tmpReg, ecx );

        inc( eax ); // ++h1
        inc( j );
   
    endwhile;
           
         
    //while( h2 <= top ) // copy any remaining entries (2nd half)
        //tmp->ary[j++] = cv->ary[h2++];
       
    while( ecx <= top ) do 
     
        mov( ecx, esi );
        intmul( rsize, esi );
        add( (type Vec [ebx]).ary, esi );

        mov( j, edi );
        intmul( rsize, edi );
        add( (type Vec [edx]).ary, edi );

        mov( ecx, tmpReg );
        mov( rsize, ecx );
        rep.movsb(); // tmp->ary[j++] = cv->ary[h2++];
        mov( tmpReg, ecx );

        inc( ecx ); // ++h2
        inc( j );
       
    endwhile;
         

    //for( j = 0; j < sz; ++j ) // copy back sorted tmp vec...
        //cv->ary[bot+j] = tmp->ary[j];
 
    mov( (type Vec [edx]).ary, esi );
    mov( bot, edi );
    intmul( rsize, edi );
    add( (type Vec [ebx]).ary, edi );
    mov( sz, ecx );
    intmul( rsize, ecx );
    rep.movsb();
       
 /*   
    for( mov( 0, ecx ); ecx < sz; inc( ecx ) ) do

        mov( ecx, esi );
        intmul( rsize, esi );
        add( (type Vec [edx]).ary, esi );
       
        mov( bot, eax );
        add( ecx, eax );
   
        mov( eax, edi );
        intmul( rsize, edi );
        add( (type Vec [ebx]).ary, edi );
       
        mov( ecx, tmpReg );
        mov( rsize, ecx );
        rep.movsb(); // cv->ary[bot+j] = tmp->ary[j];
        mov( tmpReg, ecx );
   
    endfor;
*/   

    //pop( edi ); pop( esi ); pop( ecx ); pop( eax );
end mergeVec;


procedure my_msortVec( pv: pVec in ebx; bot: int32; top: int32; ptmp: pVec in edx );
var
    mid:    int32; 
begin my_msortVec;
    mov( top, eax );
    if( bot < eax ) then
   
        add( bot, eax );    // NOW EAX HOLDS top + bot
        shr( 1, eax );      // divide by 2 ...
        mov( eax, mid );    // mid = ( bot + top ) / 2;
       
        my_msortVec( ebx, bot, mid, edx );  // sort the first half ...
        inc( mid );                         // now mid = mid +1
       
        my_msortVec( ebx, mid, top, edx );  // and the second half
       
        mergeVec( ebx, bot, top, edx );     // now merge 2 sorted chunks
 
    endif;
end my_msortVec;


procedure msortVec( var v: Vec );
var
    Rega:   dword;
    Regb:   dword;
    Regc:   dword;
    Regd:   dword;
    Regesi: dword;
    Regedi: dword;
    tmp:    Vec;
begin msortVec;
    mov( eax, Rega ); mov( ebx, Regb ); mov( ecx, Regc ); mov( edx, Regd );
    mov( esi, Regesi ); mov( edi, Regedi );
   
    mov( v, ebx );
    mov( (type Vec [ebx]).size, eax );
    if( eax > 1 ) then
   
        initVec( tmp, (type Vec [ebx]).elen );
        reserveVec( tmp, eax ); // Note: resets cap... BUT tmp size still 0
        dec( eax );
        lea( edx, tmp );        // get address of new tmp Vec into edx ...
        my_msortVec( ebx, 0, eax, edx );
       
        // NOW done ... BUT only free ary mem that held copies of pointers
        mem.free( tmp.ary );
       
    endif;
   
    mov( Regedi, edi ); mov( Regesi, esi );
    mov( Regd, edx ); mov( Regc, ecx ); mov( Regb, ebx ); mov( Rega, eax );
   
end msortVec;



// returns index if string present, else -1 ...
procedure findVec( var v: Vec; pr: dword ); @returns( "eax" );
begin findVec;
    push( ebx ); push( ecx ); push( esi ); push( edi );
   
    mov( v, ebx );
    for( mov( 0, ecx ); ecx < (type Vec [ebx]).size; inc( ecx ) ) do
        //if( myCmp(&cv->ary[i], r) == 0 )
        mov( ecx, esi );
        intmul( (type Vec [ebx]).elen, esi );
        add( (type Vec [ebx]).ary, esi );
        mov( pr, edi );
        pMyCmp( esi, edi ); // need an 'eq' cmp here ...
        breakif( eax );     // i.e. break if equal ...
    endfor;
   
    // now check loop end condition ...
    if( ecx != (type Vec [ebx]).size ) then
        mov( ecx, eax ); // found
    else
        mov( -1, eax ); // NOT found
    endif;
   
    pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end findVec;


// if int index valid, erases element there ...
procedure eraseVec( var v: Vec; index: int32 in eax );
var
    tmpReg: dword;
    rsize:  uns32;
begin eraseVec;
    push( ebx ); push( ecx ); push( esi ); push( edi );
   
    mov( v, ebx );
    mov( (type Vec [ebx]).elen, rsize );
    if( (type int32 eax) >= 0 && (type int32 eax) < (type Vec [ebx]).size ) then
       
        mov( eax, tmpReg );
        intmul( rsize, eax );
        add( (type Vec [ebx]).ary, eax );
        pFreeRec( eax ); // must pass in eax, needed here if dynamic memory
        mov( tmpReg, eax  );
     

        //if( index < cv->size-1 )
            //memcpy(&cv->ary[index], &cv->ary[index+1], (cv->size-1-index)*sizeof(Rec));
       
        mov( (type Vec [ebx]).size, ecx );
        dec( ecx ); // ecx holds size-1
        if( eax < ecx ) then
            sub( eax, ecx ); // ecx now holds (cv->size-1-index)
            intmul( rsize, ecx ); // ecx now holds bytes to copy ...
           
            mov( eax, edi );
            intmul( rsize, edi );
            add( (type Vec [ebx]).ary, edi );
            mov( edi, esi );
            add( rsize, esi );
            rep.movsb();
        endif;
       
        // now update size and return by reference (since address passed in)
        dec( (type Vec [ebx]).size );
           
    else
        mov( (type Vec [ebx]).size, ecx );
        dec( ecx ); // ecx holds size-1
        stdout.put( nl, "ERROR! Index ", index, " out of range 0..", (type int32 ecx), nl);
    endif;
   
    pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end eraseVec;


/*
void uniqueCvec( Cvec* cv, int (*myCmp) (const void* a, const void* b),
                 void (*freeVrec) (void* el) )
{
    int i = 0, j = 1;
    if( !isSortedCvec( cv, myCmp ) )
        msortCvec( cv, myCmp, freeVrec ); // first make sure, sorted order

    for( ; j < cv->size ; ++j )
    {
        if( myCmp( (cv->ary + i*cv->elen), (cv->ary + j*cv->elen) ) != 0 )
        {
            ++i;
            if( i != j ) memcpy( (cv->ary + cv->elen*i), (cv->ary + cv->elen*j),
                                  cv->elen );
        }
        else freeVrec( cv->ary + cv->elen*j );
    }

    cv->size = ++i;
}
*/


// Adapted from the above 'C' language algorithim ...
procedure xDuplicates( var v: Vec ); 
var
    k: uns32;
begin xDuplicates;
    push( ebx );
   
    mov( v, ebx );
    if( (type Vec [ebx]).size > 1 ) then // Note: need size > 1 to enter this block ...

        push( eax ); push( ecx ); push( esi ); push( edi );
       
        cld(); // re. rep.movsb() ...

        mov( 0, k );
        for( mov( 1, ecx ); ecx < (type Vec [ebx]).size; inc( ecx) ) do

            //mov( @size(MyContact), (type Vec [ebx]).elen ); // ......................debugging //

            mov( (type Vec [ebx]).elen, edi );
            intmul( k, edi ); 
            add( (type Vec [ebx]).ary, edi );
            // edi holds offset into LAST LOWER UNIQUE record compared

            mov( (type Vec [ebx]).elen, esi );
            stdout.put( "esi = ", esi, ", edi = ", edi, nl );
            intmul( ecx, esi );
            stdout.put( "esi = ", esi, ", edi = ", edi, nl );
            add( (type Vec [ebx]).ary, esi );
            // esi now holds offset into this 'i'

            //if (a[k] != a[i])
            //if( str.ine( MyBBook.theName[edi], MyBBook.theName[esi] ) ) then
           
            stdout.put( "esi = ", esi, ", edi = ", edi, nl );
            pMyCmp( esi, edi );
            if( !eax ) then // uses eax ...
                               
                inc( k ); // k=k+1; get ready for next pair of '(k,i)' to compare
                add( (type Vec [ebx]).elen, edi ); // now edi holds offset for (k+1)

                if( k != ecx ) then // i.e. if ( (k+1) != i ) then ...
                   
                    push( ecx ); // preserve ecx counter ...
                    //mov( MyBBook.theName[esi], MyBBook.theName[edi] ); // copy this new
                    //mov( MyBBook.thePhone[esi], MyBBook.thePhone[edi] );
                   
                    mov( (type Vec [ebx]).elen, ecx );
                    rep.movsb();
                   
                    pop( ecx );

                endif;           

            else    // a[k]=a[i], SO THEN goto next 'i', (i.e. ecx), but still same old 'k' though.
                    // ok to free this 'i' record since = the 'k' record below

                //str.free( MyBBook.thePhone[esi] ); // ok to free these strings               
                //str.free( MyBBook.theName[esi] );
                mov( esi, eax );
                pFreeRec( eax );

            endif;

        endfor;

        inc( k );
        mov( k, (type Vec [ebx]).size );

        pop( edi ); pop( esi ); pop( ecx ); pop( eax );

    endif;

    pop( ebx );
end xDuplicates;
« Last Edit: August 21, 2012, 08:30:27 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #10 on: August 17, 2012, 03:24:37 AM »
The list2 pair:

"sllist2.hhf"

Code: [Select]
// sllist2.hhf // 2012-08-15 //

// using NNode to avoid conflict with Node
// using SLList to avoid conflict with List

#includeOnce( "stdlib.hhf" )


// NB!!! the record NNode must be defined before including this file
// ALSO  the type pNNode: pointer to NNode;


? @nodisplay:= true; // all procedures have @nodisplay 'as default' now

type
    NNode:  record
                nval:    dword;
                next:    pointer to NNode;
            endrecord;
           
    pNNode:   pointer to NNode;

type   
    SLList: record
                head:   pNNode;
                tail:   pNNode;
                size:   uns32;   
            endrecord;
static
    pFreeNNode: procedure( pn: pNNode in eax );
 
procedure initSLList( var lst: SLList );
begin initSLList;
    push( eax ); push( ebx );
    mov( lst, ebx );
    mov( 0, (type SLList [ebx]).head );
    mov( 0, (type SLList [ebx]).tail );
    mov( 0, (type SLList [ebx]).size );
    pop( ebx ); pop( eax );
end initSLList;


procedure push_frontSLList( var lst: SLList; var n: NNode );
begin push_frontSLList;
    //push( ebx ); push( ecx ); push( esi ); push( edi ); // caller must preserve if needed
   
    cld();
    mem.alloc( @size(NNode) );
   
    mov( eax, edi );
    mov( n, esi ); // get address of new NNode into esi ...

    // get num bytes to copy in ecx ...
    mov( @size(NNode), ecx );
    rep.movsb();
   
    // ok ... now prepend (copy) of new rec ...
    mov( lst, ebx );
    if( (type SLList [ebx]).size != 0 ) then // not empty
        mov( mov( (type SLList [ebx]).head, ecx ), (type NNode [eax]).next );
        mov( eax, (type SLList [ebx]).head );
    else
        mov( 0, (type NNode [eax]).next );
        mov( eax, (type SLList [ebx]).tail );
        mov( eax, (type SLList [ebx]).head );
    endif;
   
    inc( (type SLList [ebx]).size ); // update size
 
    //pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end push_frontSLList;

procedure push_backSLList( var lst: SLList; var n: NNode );
begin push_backSLList;
    //push( ebx ); push( ecx ); push( esi ); push( edi ); // caller must preserve if needed
   
    cld();
    mem.alloc( @size(NNode) );
   
    mov( eax, edi );
    mov( n, esi ); // get address of new Rec into esi ...

    // get num bytes to copy in ecx ...
    mov( @size(NNode), ecx );
    rep.movsb();
   
    mov( 0, (type NNode [eax]).next );
   
    // ok ... now append (copy) of new rec ...
    mov( lst, ebx );
    if( (type SLList [ebx]).size != 0 ) then // not empty
        mov( (type SLList [ebx]).tail, ecx );
        mov( eax, (type NNode [ecx]).next ); // now 'next' updated
        mov( eax, (type SLList [ebx]).tail );
    else
        mov( eax, (type SLList [ebx]).tail );
        mov( eax, (type SLList [ebx]).head );
    endif;
   
    inc( (type SLList [ebx]).size ); // update size
 
    //pop( edi ); pop( esi ); pop( ecx ); pop( ebx );
end push_backSLList;


procedure clearSLList( var v: SLList );
begin clearSLList;
    push( eax ); push( ebx ); push( ecx );
   
    mov( v, ebx );
    mov( (type SLList[ebx]).head, ecx );
    while(  ecx != 0 ) do
        mov( ecx, eax );
        mov( (type NNode [ecx]).next, ecx );
        pFreeNNode( eax );             
        mem.free( eax );
    endwhile;
   
   
    initSLList( (type SLList [ebx]) );
 
    pop( ecx ); pop( ebx ); pop( eax );
end clearSLList;


Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: HLA vector and list function library ... also readLine and readWord ...
« Reply #11 on: August 17, 2012, 03:26:43 AM »
"sllist2_func's.hhf"

Code: [Select]
// sllist2_func's.hhf // // 2012-08-16 //


#includeOnce( "sllist2.hhf" )


type
    pSLList: pointer to SLList;


#if( !@defined( pMyCmp ) )
static
    pMyCmp: procedure( a: dword in esi; b: dword in edi ); @returns( "eax" );
#endif


// re. isort ... note: cmp func is a <= b (for list, ALSO same as for msort)
// re. msort ... note: cmp func is a <= b


// pass in the address of the SLList and the new Node to insert ...
procedure insert_sortedSLList( var lst: SLList; pn: pNNode in eax );
//var
    //head: pNNode; // esi
var
    reg32:  dword;
begin insert_sortedSLList;
    push( ebx ); push( esi ); push( edi );
   
    //pList head;
    //if( !isSortedSLList( list, myCmp )) msortSLList( list, myCmp );
    //head = list->start;
    mov( lst, ebx );
    mov( (type SLList [ebx]).head, esi );
    mov( eax , edi );
   
    // firstly, we handle most common case where 'n' is NOT the first Node
    //if( head != NULL && myCmp( n, head ) >= 0 ) // NEED >=
    if( esi && pMyCmp( esi, edi ) ) then
        // so search the linked list for the right location
        //pList cur = head;
        //while( cur->next != NULL && myCmp( cur->next, n ) <= 0 )
        mov( esi, reg32 );
        mov( (type NNode [esi]).next, esi );
        //while( esi && pmyCmp( esi, edi ) ) do
        forever
            if( !esi || !pMyCmp( esi, edi ) ) then
                //cur = cur->next;
                mov( reg32, esi );
                break;
            else
                mov( esi, reg32 );
                mov( (type NNode [esi]).next, esi );
            endif;
        endfor;
       
        //if( cur == list->end ) list->end = n;
        if( esi == (type SLList [ebx]).tail ) then
            mov( edi, (type SLList [ebx]).tail );
        endif;
       
        //n->next = cur->next;
        mov( (type NNode [esi]).next, (type NNode [edi]).next );
       
        //cur->next = n;
        mov( edi, (type NNode [esi]).next );
       
        // list->start = head; // unchanged //
        //++ list->size;
        inc( (type SLList [ebx]).size );
    else // if we reach here, this IS the first node ...
        //n->next = head; // so set this node in first position
        mov( (type SLList [ebx]).head, (type NNode [edi]).next );
        //list->start = n;
        mov( edi, (type SLList [ebx]).head );
        //++ list->size;
        inc( (type SLList [ebx]).size );
        if( (type SLList [ebx]).size == 1 ) then
            // list->end = n;
            mov( edi, (type SLList [ebx]).tail );
        endif;
    endif;
   
    pop( edi ); pop( esi ); pop( ebx );
end insert_sortedSLList;

//void isortSLList( SLList* list, int (*myCmp) (const pList r1, const pList r2) )
procedure isortSLList( var lst: SLList );
var
    nSLList:    SLList;
    //cur:        pNNode; // eax
    //nextNode:   pNNode; // ecx
begin isortSLList;
    push( eax ); push( ebx ); push( ecx );
   
    initSLList( nSLList );
    mov( lst, ebx );
    //for( cur = list->start; cur != NULL; cur = nextNode )
    for( mov( (type SLList [ebx]).head, eax ); eax; mov( ecx, eax ) ) do
        //nextNode = cur->next; // get copy here before next is changed below
        mov( (type NNode [eax]).next, ecx );
        //insert_sortedSLList( &nSLList, cur, myCmp ); // 'cur' already is a Node pointer
        insert_sortedSLList( nSLList, eax );
    endfor;
     
    // now ... update old list with new front and back ...
    //list->start = nSLList.start;
    mov( nSLList.head, (type SLList [ebx]).head );
    //list->end = nSLList.end;
    mov( nSLList.tail, (type SLList [ebx]).tail );
   
    // size hasn't changed 

    pop( ecx ); pop( ebx ); pop( eax );
end isortSLList;


// merge two sorted SLLists with heads 'a' and 'b' ... in sorted order
procedure mergeSLLists(var a: SLList; var b: SLList ); @returns( "eax" ); // new head
var
    newMergedHead:  dword;
    //sorted:         dword; // use ebx // using edx now ..
begin mergeSLLists;
    //push( ebx ); // using edx instead of ebx here now ...
    //push( esi ); push( edi );

    //pList sorted, new_merged_head;
    mov( a, eax );
    mov( (type SLList [eax]).head, esi );
    mov( b, eax  );
    mov( (type SLList [eax]).head, edi );
   
    //if( a->start == NULL ) return b->start;
    //if( b->start == NULL ) return a->start;
    if( !esi ) then mov( edi, newMergedHead );
    elseif( !edi ) then mov( esi, newMergedHead );
   
    else
        //if( myCmp(a->start, b->start) <= 0 )
        if( pMyCmp( esi, edi ) ) then
            //sorted = a->start;
            //a->start = a->start->next;
            mov( esi, edx );
            mov( (type NNode [esi]).next, esi );
        else
            //sorted = b->start;
            //b->start = b->start->next;
            mov( edi, edx );
            mov( (type NNode [edi]).next, edi );
        endif;
       
        //new_merged_head = sorted;
        mov( edx, newMergedHead );

        // now ...
        //while( a->start != NULL && b->start != NULL )
        while( esi && edi ) do
            //if( myCmp(a->start, b->start) <= 0 )
            if( pMyCmp( esi, edi ) ) then
                //sorted->next = a->start;
                mov( esi, (type NNode [edx]).next );
                //sorted = a->start;
                mov( esi, edx );
                //a->start = a->start->next;
                mov( (type NNode [esi]).next, esi );   
            else
                //sorted->next = b->start;
                mov( edi, (type NNode [edx]).next );
                //sorted = b->start;
                mov( edi, edx );
                //b->start = b->start->next;
                mov( (type NNode [edi]).next, edi );
            endif;
        endwhile;

        // and finally ...
        //if( a->start != NULL )
        if( esi ) then
            //sorted->next = a->start;
            mov( esi, (type NNode [edx]).next );
        //else if( b->start != NULL )
        elseif( edi ) then
            //sorted->next = b->start;
            mov( edi, (type NNode [edx]).next );
        endif;
   
    endif;

    mov( newMergedHead, eax );
   
    //pop( edi ); pop( esi );
    //pop( ebx );
end mergeSLLists;


// a recursive mergesort ...
procedure mergesortSLList( var lst: SLList );
var
    // cur:    pNNode; // ecx
    a:      SLList;
    b:      SLList;
begin mergesortSLList;
    push( ebx );
    //push( ecx ); push( edx );
    //pList cur = list->start;
    mov( lst, ebx );
    mov( (type SLList [ebx]).head, ecx );
    mov( ecx, a.head );
    //SLList a, b;

    // base case is a SLList of length 0 or 1 ...
    //if ((cur == NULL) || (cur->next == NULL))  return;
   
    if( a.head != 0 /*&& b.head != 0*/ ) then
        mov( (type NNode [ecx]).next, b.head );
        if( b.head != 0 ) then
            // split SLList into 'a' and 'b' sublists ...
            //a.start = cur;
            //b.start = cur->next; // both these lines done above
            while( b.head != 0 /*&& ( b.start->next != NULL)*/  ) do
                mov( b.head, edx );
                mov( (type NNode [edx]).next, edx );
                breakif( !edx );
               
                //cur = cur->next;
                mov( (type NNode [ecx]).next, ecx );
                //b.start = b.start->next->next;
                mov( (type NNode [edx]).next, b.head );
            endwhile;

            //b.start = cur->next;
            mov( (type NNode [ecx]).next, b.head );
           
            //cur->next = NULL; // SLList divided into 2 roughly equal parts now
            mov( 0, (type NNode [ecx]).next );

            // recursively sort the sublists ...
            mergesortSLList( a );
            mergesortSLList( b );

            // merge the two sorted SLLists together ...
            //list->start = mergeSLLists(&a, &b, myCmp);
            mergeSLLists( a, b ); // returns new merged head in eax
            mov( eax, (type SLList [ebx]).head );
        endif;
    endif;
    //pop( edx ); pop( ecx );
    pop( ebx );
end mergesortSLList;

 
procedure update_endSLList( var lst: SLList ); // after sort
begin update_endSLList;
    //push( ebx ); push( ecx );
   
    mov( lst, ebx );
    if( (type SLList [ebx]).size > 1 ) then
        //pList cur;
        //for( cur = list->start; cur->next != NULL; cur = cur->next ) ;
        //list->end = cur;
        //list->end->next = NULL; // this line NOT-needed/redundant
        mov( (type SLList [ebx]).head, ecx );
        while( (type NNode [ecx]).next != 0 ) do mov( (type NNode [ecx]).next, ecx ); endwhile;
        mov( ecx, (type SLList [ebx]).tail );
    endif;
   
    //pop( ecx ); pop( ebx );
end update_endSLList;


procedure msortSLList( var lst: SLList );
var
    Rega:   dword;
    Regb:   dword;
    Regc:   dword;
    Regd:   dword;
    Regesi: dword;
    Regedi: dword;
begin msortSLList;
    mov( eax, Rega ); mov( ebx, Regb ); mov( ecx, Regc ); mov( edx, Regd );
    mov( esi, Regesi ); mov( edi, Regedi );
   
    mov( lst, ebx );
    mergesortSLList( (type SLList [ebx]) );
    //mov( lst, ebx );
    update_endSLList( (type SLList [ebx]) );

    mov( Regedi, edi ); mov( Regesi, esi );
    mov( Regd, edx ); mov( Regc, ecx ); mov( Regb, ebx ); mov( Rega, eax );
end msortSLList;



// returns pointer if present, else returns 0
procedure findSLList( var lst: SLList; var nn: NNode ); @returns( "eax" );
begin findSLList;
    push( ebx ); push( esi ); push( edi );
   
   
    //pList p;
    mov( lst, ebx );
    mov( nn, edi );
    //for( p = cl->start; p != NULL; p = p->next )
    for( mov( (type SLList [ebx]).head, esi ); esi; mov( (type NNode [esi]).next, esi ) ) do
        //if( myCmp(p, pr) == 0 ) return p;
        pMyCmp( esi, edi ); // returns eax = 1 if found, else 0
        if( eax ) then
            mov( esi, eax );
            break;
        endif;
    endfor;
    // if not found above, eax is already 0
   
    pop( edi ); push( esi ); push( ebx );
end findSLList;


procedure eraseSLList( var lst: SLList;  pn: pNNode in eax ); // if pn valid, erase element there
//var
    //prev:   pNNode; // use edx
begin eraseSLList;
    push( ebx ); push( ecx ); push( edx );
   
    //pList prev = NULL, cur = cl->start;
    mov( 0, edx );
    mov( lst, ebx );
   
    for( mov( (type SLList [ebx]).head, ecx ); ecx && ecx != eax; mov( (type NNode [ecx]).next, ecx ) ) do
        //prev = cur;
        mov( ecx, edx );
    endfor;
   
    if( ecx ) then
       
        if( edx ) then // case of NOT FIRST element
            //prev->next = cur->next;
            mov( (type NNode [ecx]).next, (type NNode [edx]).next );
        else // case of IS FIRST element
            //cl->start = cl->start->next;
            mov( (type NNode [ecx]).next, (type SLList [ebx]).head );
        endif;
       
        //if( cur == cl->end ) cl->end = prev; /* case of IS LAST element*/
        if( ecx == (type SLList [ebx]).tail ) then
            mov( edx, (type SLList [ebx]).tail );
        endif;

        pFreeNNode( ecx ); // needed here for types like dynamic C strings, etc
        mem.free( ecx ); // free memory for dynamic Node ...

        // now update size and return (by reference, since address passed in)
        //-- cl->size;
        dec(  (type SLList [ebx]).size );
       
    else
        stdout.puts( nl "eraseSLList ERROR! Pointer NOT found ..." );
    endif;
   
    pop( edx ); pop( ecx ); pop( ebx );
end eraseSLList;



#if( !@defined( chrIsInStr ) )
    // returns *POSITION*  1..n  (POS = INDEX+1)  or  0 if NOT found //
    procedure chrIsInStr( c: char in al; s: string ); @returns( "eax" );
    begin chrIsInStr;
        str.chpos( s, al );
        inc( eax );
    end chrIsInStr;
#endif


procedure splitSLList( var sll: SLList; s: string; delims: string );
var
    myNNode:    NNode;
    reg32:      dword;
    i:          uns32;
begin splitSLList;
    push( eax ); push( ebx ); push( ecx ); push( edx );
   
    mov( sll, ebx );
    mov( s, ecx ); // ecx holds start address ...
   
    forever
   
        while( chrIsInStr( (type char [ecx]), delims ) ) do
            inc( ecx );
        endwhile;
       
        breakif( (type char [ecx]) == 0 ); // since 'empty' string
       
        mov( ecx, edx );
        inc( edx ); // edx holds address one past end of 'word' ...
       
        mov( (type char [edx]), al );
        while( al && !chrIsInStr( al, delims ) ) do
            inc( edx );
            mov( (type char [edx]), al );
        endwhile;
       
        mov( edx, reg32 );  // save a copy of 'end' in reg32 ...
        sub( ecx, edx );    // edx holds 'len of next word'
       
        mov( ecx, i );
        mov( s, eax );
        sub( eax, i );      // i is index to start
       
        str.a_substr( s, i, edx ); // start, len
        mov( eax, myNNode.nval );
       
        push_backSLList( (type SLList [ebx]), myNNode );
       
        mov( reg32, ecx );  // update (next) start pointer ecx ...
   
    endfor;
 
    pop( edx ); pop( ecx ); pop( ebx ); pop( eax );
end splitSLList;


procedure uniqueSLList( var lst: SLList );
begin uniqueSLList;
    push( eax ); push( ebx ); push( esi ); push( edi );

    //pList p = c->start;
    mov( lst, ebx );
    mov( (type SLList [ebx]).head, esi ); // esi holds cur NNode address
   
    if( esi ) then
        //while( p->next != NULL )
        while( (type NNode [esi]).next != 0 ) do
            //if( myCmp(p, p->next) == 0 )
            mov( (type NNode [esi]).next, edi );
            if( pMyCmp( esi, edi ) ) then // if equal then ...
                //pList tmp = p->next;
                mov( edi, eax ); // eax is tmp copy ...
               
                //p->next = p->next->next;
                mov( (type NNode [edi]).next, edi ); // now advance edi ...
                mov( edi, (type NNode [esi]).next );
               
                pFreeNNode( eax ); // needed here for types like dynamic Cstrings, etc
                mem.free( eax );
                //-- c->size;
                dec( (type SLList [ebx]).size );
            else
                //p = p->next;
                mov( edi, esi ); // mov esi up since not equal ...
            endif;
        endwhile;
   
        update_endSLList( (type SLList [ebx]) ) ; // update end ...
    endif;
   
    pop( edi ); pop( esi ); pop( ebx ); pop( eax );
end uniqueSLList;
« Last Edit: August 21, 2012, 08:31:29 AM by David »