SDCC and recursion and MSX-DOS2

Page 2/2
1 |

By msd

Paragon (1515)

msd's picture

01-04-2023, 09:07

Btw you can just allocate an array of 31 FIBS. It is not possible to got more than 31 levels deeps, because max path is 63.

By rolandve

Champion (358)

rolandve's picture

01-04-2023, 09:34

My assembly is broken. Somehow the program terminates after walk("*.*"). When I run this on a dir as floppy, I sometime get the question to change the system time.

    while (!ret) {
        if (fibStore->Filename[0] != '.') {
            // debug -> address of the FIB structure
            String_Format(outBuf,"%i\n\r$",fibStore);
            DOS_StringOutput(outBuf);
            // display filename
            String_Format(outBuf,"%s\n\r$",fibStore->Filename);
            DOS_StringOutput(outBuf);
            // is a directory?
            if ((fibStore->Attribute & 0x10) == 0x10 ) {
                DOS_ChangeDir(fibStore->Filename);
                walk("*.*");
                DOS_StringOutput("Are we back?$");  //<- this line will never be executed
            }

        }
        //fib = DOS_FindNextEntry();
        ret = FNext(fibStore);
    }

By aoineko

Paladin (1002)

aoineko's picture

01-04-2023, 12:08

I think there is a confusion in the use of Mem_HeapAlloc / Mem_HeapFree function.
As said before, it is a flat allocator; extremely fast, but that can only be used for static memory allocation or temporary buffer.
Mem_HeapFree() takes a size as a parameter while you pass it a pointer.
If you are sure that all the allocations are linear (which should be the case with a recursive directory tree), you can use this function with the size of the FIB structure.

Otherwise you can use the dynamic allocator which is more expensive (even if I optimized it for the z80) but works like the one in C.
There is an example of use in the sample s_sys.

By rolandve

Champion (358)

rolandve's picture

02-04-2023, 09:45

The working code

//**************************************************************************
//*   recursively walk a directory tree
//*   dialect : MSXgl
//**************************************************************************

#include 
#include 
#include 

// at this location there is BASIC buffer which is unused, use for 256Bytes
u8 __at(0xF55E) outBuf[256];


// Change Directory
u8 DOS_ChangeDir(const c8* path)
{
	path; // HL
__asm
	ex de,hl
	ld c, #DOS_FUNC_CHDIR      // DOS routine
	call BDOS
    ret
__endasm;
}

// Find First File
// requires a *FIB so each recursion can have its own FIB
// c8* search pattern
u8 FFirst(DOS_FIB* fib,const c8* param)
// fib HL
// param DE
{
        fib; //HL
        param; //DE

__asm
    push ix
    ld b,#0x37 // attributes
    ld c,#0x40 // Find First File
    push hl
    pop ix
    call BDOS
    pop ix
__endasm;
}

// continue search with *FIB
u8 FNext(DOS_FIB* fib)
// fib HL
{
    fib; //HL
__asm
    push ix //save ix
    push hl
    pop ix
    xor b // b == 0
    ld c,#0x41 // fnext
    call BDOS
    pop ix
__endasm;
}

void walk(const u8* param)
{
    u8 ret;
    Mem_Set('$',outBuf,15);
    DOS_FIB* fibStore =(DOS_FIB*)Mem_HeapAlloc(sizeof(DOS_FIB));
    ret = FFirst(fibStore,param);
    while (!ret) {
        if (fibStore->Filename[0] != '.') {
            String_Format(outBuf,"%s\n\r$",fibStore->Filename);
            DOS_StringOutput(outBuf);
            if ((fibStore->Attribute & 0x10) == 0x10 ) {
                DOS_ChangeDir(fibStore->Filename);
                walk("*.*");
                DOS_ChangeDir("..");
            }

        }
        ret = FNext(fibStore);
    }
    Mem_HeapFree(sizeof(DOS_FIB));
    
}

void main()
{
    walk("*.*"); // this is the current directory
}
Page 2/2
1 |