Problem with vsnprintf

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Stefan123
Member
Posts: 85
Joined: Fri Oct 21, 2016 7:57 am

Problem with vsnprintf

Post by Stefan123 »

I want to have a debugging function that writes formatted output to a log file like the example below:

Code: Select all

static char dbg_buf[128];

static void page_in_rom(void)
{
    ZXN_WRITE_MMU0(255);
    ZXN_WRITE_MMU1(255);
}

static void page_out_rom(void)
{
    ZXN_WRITE_MMU0(current_page);
    ZXN_WRITE_MMU1(current_page + 1);
}

void dbg_print(char *format, ...)
{
    int size;
    va_list args;

    va_start(args, format);
    size = vsnprintf(dbg_buf, sizeof(dbg_buf), format, args);
    va_end(args);

    page_in_rom();
    esxdos_f_write(dbg_log, dbg_buf, size);
    page_out_rom();
}
However, the written output in the log file contains a lot of junk characters and sometimes the program crashes horribly. If I use snprintf() it works but I really need vsnprintf() for this use case. I use SCCZ80 (and zxn target) since the programs takes too long time to compile with SDCC during development.
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

All var arg functions have to be dealt with specially with sccz80 because sccz80 pushes arguments in left to right order.

Here's an example that works with both sccz80 and zsdcc with the help of some conditional code:

Code: Select all

int error(char *fmt, ...)
{
   unsigned char *p;
   
   va_list v;
   va_start(v, fmt);

#ifdef __SCCZ80
   vsnprintf(ebuf, sizeof(ebuf), va_ptr(v,char *), v);
#else
   vsnprintf(ebuf, sizeof(ebuf), fmt, v);
#endif

   for (p = ebuf; p = strchr(p, '\n'); )
      *p = '\r';
   
   ebuf[strlen(ebuf)-1] += 0x80;  
   return (int)ebuf;
}
For sccz80, a special macro has to be used to find the address of the fmt string.
Stefan123
Member
Posts: 85
Joined: Fri Oct 21, 2016 7:57 am

Post by Stefan123 »

Thanks :) I changed my code to the following and now it works:

Code: Select all

void dbg_print(char *format, ...)
{
    int size;
    va_list args;

    va_start(args, format);
#ifdef __SCCZ80
    size = vsnprintf(dbg_buf, sizeof(dbg_buf), va_ptr(args, char *), args);
#else
    size = vsnprintf(dbg_buf, sizeof(dbg_buf), format, args);
#endif
    va_end(args);

    page_in_rom();
    esxdos_f_write(dbg_log, dbg_buf, size);
    page_out_rom();
}
Post Reply