/* PUT.C -- STDERR output routines, no malloc */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dos.h>
#include <bios.h>

#define STDERR          2

#include "put.h"

// returns length of far string
#ifdef _MSC_VER
#define fstrlen(s)      _fstrlen(s)     // MSC 6.0
#else
size_t fstrlen(const char far *s)       // MSC 5.1
{
    size_t len = 0;
    while (*s++) len++;
    return len;
}
#endif

unsigned doswrite(int handle, char far *s, unsigned len)
{
    unsigned bytes;
    _dos_write(handle, s, len, &bytes);
    return bytes;
}

unsigned put_str(char far *s)
{
    return doswrite(STDERR, s, fstrlen(s));
}

unsigned put_chr(int c)
{
    return doswrite(STDERR, (void far *) &c, 1);
}

#define putstr(s)   { put_str(s); put_str("\r\n"); }

#define MAX_WID     12

unsigned put_num(unsigned long u, unsigned wid, unsigned radix)
{
    char buf[MAX_WID+1], *p;
    int i, digit;
    if (wid > MAX_WID)
        return;
    for (i=wid-1, p=&buf[wid-1]; i >= 0; i--, p--, u /= radix)
    {
        digit = u % radix;
        *p = digit + ((digit < 10) ? '0' : 'A' - 10);
    }
    buf[wid] = 0;
    return doswrite(STDERR, (void far *) buf, wid);
}

#define put_hex(u)      put_num(u, 4, 16)
#define put_long(ul)    put_num(ul, 9, 10)

int _FAR_ _cdecl printf(const char _FAR_ *fmt, ...)
{
    static char buf[128];
    int len;
    va_list marker;
    va_start(marker, fmt);
    len = vsprintf(buf, fmt, marker); 
    va_end(marker);
    return doswrite(STDERR, (void far *) buf, len);
}

unsigned get_str(char far *s, unsigned len)
{
    extern void (interrupt far *old_int28)(void);
    unsigned rcount;
    
    /* give TSRs a chance by calling INT 28h */
    while (! _bios_keybrd(_KEYBRD_READY))
        (*old_int28)();
    
    if ((_dos_read(STDERR, s, len, &rcount) != 0) || (rcount < 3))
        return 0;
    s[rcount-2] = '\0';
    return rcount-2;
}
