mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-01-15 00:56:39 +00:00
1145 lines
22 KiB
HolyC
Executable file
1145 lines
22 KiB
HolyC
Executable file
U0 SPutChar(U8 **_dst, U8 ch, U8 **_buf)
|
||
{
|
||
I64 i;
|
||
U8 *dst = *_dst, *buf;
|
||
|
||
if (_buf)
|
||
{
|
||
buf = *_buf;
|
||
i = dst - buf;
|
||
if (i >= MSize(buf))
|
||
{
|
||
buf = MAlloc(i << 1 + 1);
|
||
MemCopy(buf, *_buf, i);
|
||
Free(*_buf);
|
||
dst = buf + i;
|
||
*_buf = buf;
|
||
}
|
||
}
|
||
*dst++ = ch;
|
||
*_dst = dst;
|
||
}
|
||
|
||
U0 OutStr(U8 *ptr, U8 **_buf, U8 **_dst, I64 len, I64 flags)
|
||
{
|
||
I64 i, j;
|
||
|
||
if (!ptr)
|
||
i = 0;
|
||
else
|
||
i = StrLen(ptr);
|
||
if (flags & PRINTF_TRUNCATE && i > len)
|
||
i = len;
|
||
if (flags & PRINTF_LEFT_JUSTIFY)
|
||
{
|
||
for (j = 0; j < i; j++)
|
||
SPutChar(_dst, *ptr++, _buf);
|
||
for (j = 0; j < len - i; j++)
|
||
SPutChar(_dst, CH_SPACE, _buf);
|
||
}
|
||
else
|
||
{
|
||
for (j = 0; j < len - i; j++)
|
||
SPutChar(_dst, CH_SPACE, _buf);
|
||
for (j = len - i; j < len; j++)
|
||
SPutChar(_dst, *ptr++, _buf);
|
||
}
|
||
}
|
||
|
||
U8 *MPrintTime(CDate cdt)
|
||
{
|
||
CDateStruct ds;
|
||
|
||
Date2Struct(&ds, cdt + local_time_offset);
|
||
return MStrPrint("%02d:%02d:%02d", ds.hour, ds.min, ds.sec);
|
||
}
|
||
|
||
U8 *MPrintDate(CDate cdt)
|
||
{
|
||
CDateStruct ds;
|
||
|
||
Date2Struct(&ds, cdt + local_time_offset);
|
||
return MStrPrint("%02d/%02d/%02d", ds.mon, ds.day_of_mon, ds.year % 100);
|
||
}
|
||
|
||
U8 *MPrintQ(U8 *ptr, I64 flags)
|
||
{
|
||
U8 **_buf, *buf, **_dst, *dst, buf2[8], *ptr2;
|
||
I64 ch;
|
||
|
||
buf = MAlloc(STR_LEN);
|
||
_buf = &buf;
|
||
dst = buf;
|
||
_dst = &dst;
|
||
if (ptr)
|
||
while (ch = *ptr++)
|
||
{
|
||
switch (ch)
|
||
{
|
||
case '$$':
|
||
if (flags & PRINTF_DOLLAR)
|
||
{
|
||
SPutChar(_dst, '\\', _buf);
|
||
SPutChar(_dst, 'd', _buf);
|
||
}
|
||
else
|
||
{
|
||
SPutChar(_dst, ch, _buf);
|
||
SPutChar(_dst, ch, _buf);
|
||
}
|
||
break;
|
||
|
||
case '%':
|
||
SPutChar(_dst, ch, _buf);
|
||
if (flags & PRINTF_SLASH)
|
||
SPutChar(_dst, ch, _buf);
|
||
break;
|
||
|
||
case '\n':
|
||
SPutChar(_dst, '\\', _buf);
|
||
SPutChar(_dst, 'n', _buf);
|
||
break;
|
||
|
||
case '\r':
|
||
SPutChar(_dst, '\\', _buf);
|
||
SPutChar(_dst, 'r', _buf);
|
||
break;
|
||
|
||
case '\t':
|
||
SPutChar(_dst, '\\', _buf);
|
||
SPutChar(_dst, 't', _buf);
|
||
break;
|
||
|
||
case '"':
|
||
case '\\':
|
||
SPutChar(_dst, '\\', _buf);
|
||
SPutChar(_dst, ch, _buf);
|
||
break;
|
||
|
||
default:
|
||
if (ch >= CH_SPACE && ch != 0x7F)
|
||
SPutChar(_dst, ch, _buf);
|
||
else
|
||
{
|
||
StrPrint(buf2, "\\x%02X", ch);
|
||
ptr2 = buf2;
|
||
while (*ptr2)
|
||
SPutChar(_dst, *ptr2++, _buf);
|
||
}
|
||
}
|
||
}
|
||
SPutChar(_dst, 0, _buf);
|
||
return buf;
|
||
}
|
||
|
||
U8 *MPrintq(U8 *ptr, I64 flags)
|
||
{
|
||
U8 **_buf, *buf, **_dst, *dst;
|
||
I64 i, j, ch, ch1;
|
||
|
||
buf = MAlloc(STR_LEN);
|
||
_buf = &buf;
|
||
dst = buf;
|
||
_dst = &dst;
|
||
if (ptr)
|
||
while (ch =*ptr++)
|
||
{
|
||
ch1 = *ptr;
|
||
switch (ch)
|
||
{
|
||
case '\\':
|
||
switch (ch1)
|
||
{
|
||
start:
|
||
case '0':
|
||
SPutChar(_dst, 0, _buf);
|
||
break;
|
||
|
||
case '\'':
|
||
SPutChar(_dst, '\'', _buf);
|
||
break;
|
||
|
||
case '\`':
|
||
SPutChar(_dst, '\`', _buf);
|
||
break;
|
||
|
||
case '"':
|
||
SPutChar(_dst, '"', _buf);
|
||
break;
|
||
|
||
case '\\':
|
||
SPutChar(_dst, '\\', _buf);
|
||
break;
|
||
|
||
case 'd':
|
||
SPutChar(_dst, '$$', _buf);
|
||
break;
|
||
|
||
case 'n':
|
||
SPutChar(_dst, '\n', _buf);
|
||
break;
|
||
|
||
case 'r':
|
||
SPutChar(_dst, '\r', _buf);
|
||
break;
|
||
|
||
case 't':
|
||
SPutChar(_dst, '\t', _buf);
|
||
break;
|
||
end:
|
||
ptr++;
|
||
break;
|
||
|
||
case 'x':
|
||
case 'X':
|
||
i = 0;
|
||
ptr++;
|
||
for (j = 0; j < 2; j++)
|
||
{
|
||
ch1 = ToUpper(*ptr++);
|
||
if (Bt(char_bmp_hex_numeric, ch1))
|
||
{
|
||
if (ch1 <= '9')
|
||
i = i << 4 + ch1 - '0';
|
||
else
|
||
i = i << 4 + ch1 - 'A' + 10;
|
||
}
|
||
else
|
||
{
|
||
ptr--;
|
||
break;
|
||
}
|
||
}
|
||
SPutChar(_dst, i, _buf);
|
||
break;
|
||
|
||
default:
|
||
SPutChar(_dst, ch, _buf);
|
||
}
|
||
break;
|
||
|
||
case '$$':
|
||
SPutChar(_dst, ch, _buf);
|
||
if (ch1 == '$$')
|
||
ptr++;
|
||
break;
|
||
|
||
case '%':
|
||
SPutChar(_dst, ch, _buf);
|
||
if (flags & PRINTF_SLASH && ch1 == '%')
|
||
ptr++;
|
||
break;
|
||
|
||
default:
|
||
SPutChar(_dst, ch, _buf);
|
||
}
|
||
}
|
||
SPutChar(_dst, 0, _buf);
|
||
return buf;
|
||
}
|
||
|
||
U8 *sys_pos_pows_lets = " KMGTPEZY",
|
||
*sys_neg_pows_lets = " m<>npfazy",
|
||
*sys_pos_pows_list = "kilo\0mega\0giga\0tera\0peta\0exa\0zetta\0yotta\0",
|
||
*sys_neg_pows_list = "milli\0micro\0nano\0pico\0femto\0atto\0zepto\0yocto\0";
|
||
|
||
#define TMP_BUF_LEN 256
|
||
#define SLOP 8
|
||
|
||
U8 *StrPrintJoin(U8 *dst, U8 *format, I64 argc, I64 *argv)
|
||
{/*$LK,"Print(\"\") Format Strings",A="FI:::/Doc/Print.DD"$
|
||
In float formatting, do not exceed 18-digits
|
||
before or after the decimal point
|
||
because the numbers before and after
|
||
the decimal point are stored
|
||
in 64-bits. Use exponentiated forms
|
||
to avoid this.
|
||
*/
|
||
I64 i, j, l, ch, k, k0, n, n0,
|
||
len, dec_len, flags, old_flags,
|
||
aux_format_num, comma_count, comma_format_count, cur_arg=0;
|
||
U64 m;
|
||
F64 d, d1;
|
||
CDoc *doc;
|
||
U8 *ptr, **_buf, *buf, **_dst, tmp_buf[TMP_BUF_LEN], tmp_buf2[TMP_BUF_LEN*2];
|
||
|
||
if (!format)
|
||
throw('StrPrint');
|
||
if (dst)
|
||
{
|
||
_buf = NULL;
|
||
buf = dst;
|
||
}
|
||
else
|
||
{
|
||
buf = MAlloc(STR_LEN);
|
||
_buf = &buf;
|
||
dst = buf;
|
||
}
|
||
_dst = &dst;
|
||
|
||
while (ch = *format++)
|
||
{
|
||
if (ch == '%')
|
||
{
|
||
flags = 0;
|
||
if (*format == '-')
|
||
{
|
||
flags |= PRINTF_LEFT_JUSTIFY;
|
||
format++;
|
||
}
|
||
if (*format == '0')
|
||
{
|
||
flags |= PRINTF_PAD_ZERO;
|
||
format++;
|
||
}
|
||
len = 0;
|
||
while ('0' <= *format <= '9')
|
||
len = len * 10 + *format++ - '0';
|
||
if (*format == '*')
|
||
{
|
||
format++;
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
len = argv[cur_arg++];
|
||
}
|
||
dec_len = 0;
|
||
if (*format == '.')
|
||
{
|
||
format++;
|
||
while ('0' <= *format <= '9')
|
||
dec_len = dec_len * 10 + *format++ - '0';
|
||
if (*format == '*')
|
||
{
|
||
format++;
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
dec_len = argv[cur_arg++];
|
||
}
|
||
flags |= PRINTF_DECIMAL;
|
||
}
|
||
|
||
aux_format_num = 0;
|
||
while (TRUE)
|
||
{
|
||
switch (*format)
|
||
{
|
||
start:
|
||
case '$$':
|
||
flags |= PRINTF_DOLLAR;
|
||
break;
|
||
|
||
case '/':
|
||
flags |= PRINTF_SLASH;
|
||
break;
|
||
|
||
case ',':
|
||
flags |= PRINTF_COMMA;
|
||
break;
|
||
|
||
case 't':
|
||
flags |= PRINTF_TRUNCATE;
|
||
break;
|
||
|
||
case 'l': //harmless
|
||
break;
|
||
end:
|
||
format++;
|
||
break;
|
||
|
||
case 'h':
|
||
format++;
|
||
flags |= PRINTF_AUX_FORMAT_NUM;
|
||
if (*format == '?')
|
||
{
|
||
format++;
|
||
flags |= PRINTF_QUESTION;
|
||
}
|
||
else
|
||
{
|
||
if (*format == '*')
|
||
{
|
||
format++;
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
aux_format_num = argv[cur_arg++];
|
||
}
|
||
else
|
||
{
|
||
if (*format == '-')
|
||
{
|
||
format++;
|
||
flags |= PRINTF_NEG_AUX_FORMAT_NUM;
|
||
}
|
||
while ('0' <= *format <= '9')
|
||
aux_format_num = aux_format_num * 10 + *format++ - '0';
|
||
if (flags & PRINTF_NEG_AUX_FORMAT_NUM)
|
||
aux_format_num = -aux_format_num;
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
goto sp_arg;
|
||
}
|
||
}
|
||
|
||
sp_arg:
|
||
k = 0;
|
||
switch (*format++)
|
||
{
|
||
start:
|
||
case 'F':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
if (flags & PRINTF_DOLLAR)
|
||
{
|
||
doc = argv[cur_arg++];
|
||
old_flags = doc->flags;
|
||
doc->flags |= DOCF_NO_CURSOR;
|
||
ptr = DocSave(doc);
|
||
doc->flags = old_flags;
|
||
}
|
||
else
|
||
ptr = FileRead(argv[cur_arg++]);
|
||
break;
|
||
|
||
case 'Q':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
ptr = MPrintQ(argv[cur_arg++], flags);
|
||
break;
|
||
|
||
case 'q':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
ptr = MPrintq(argv[cur_arg++], flags);
|
||
break;
|
||
|
||
case 'D':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
ptr = MPrintDate(argv[cur_arg++]);
|
||
break;
|
||
|
||
case 'T':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
ptr = MPrintTime(argv[cur_arg++]);
|
||
break;
|
||
end:
|
||
OutStr(ptr, _buf, _dst, len, flags);
|
||
Free(ptr);
|
||
break;
|
||
|
||
start:
|
||
case 's':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
ptr = argv[cur_arg++];
|
||
break;
|
||
|
||
case 'S':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
ptr = Define(argv[cur_arg++]);
|
||
break;
|
||
|
||
case 'z':
|
||
if (cur_arg + 1 >= argc)
|
||
throw('StrPrint');
|
||
ptr = ListSub(argv[cur_arg], argv[cur_arg + 1]);
|
||
cur_arg = cur_arg + 2;
|
||
break;
|
||
|
||
case 'Z':
|
||
if (cur_arg + 1 >= argc)
|
||
throw('StrPrint');
|
||
ptr = DefineSub(argv[cur_arg], argv[cur_arg + 1]);
|
||
cur_arg = cur_arg + 2;
|
||
break;
|
||
end:
|
||
OutStr(ptr, _buf, _dst, len, flags);
|
||
break;
|
||
|
||
start:
|
||
case 'c':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
tmp_buf[0](I64) = argv[cur_arg++];
|
||
tmp_buf[8] = 0;
|
||
break;
|
||
|
||
case 'C':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
tmp_buf[0](I64) = argv[cur_arg++];
|
||
tmp_buf[8] = 0;
|
||
ptr = tmp_buf;
|
||
while (*ptr)
|
||
{
|
||
*ptr = ToUpper(*ptr);
|
||
ptr++;
|
||
}
|
||
break;
|
||
end:
|
||
if (!(flags & PRINTF_AUX_FORMAT_NUM))
|
||
aux_format_num = 1;
|
||
while (aux_format_num-- > 0)
|
||
OutStr(tmp_buf, _buf, _dst, len, flags);
|
||
break;
|
||
|
||
case 'p':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
StrPrintFunSeg(tmp_buf, argv[cur_arg++], len, flags);
|
||
OutStr(tmp_buf, _buf, _dst, len, flags);
|
||
break;
|
||
|
||
case 'P':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
StrPrintFunSeg(tmp_buf, argv[cur_arg], len, flags);
|
||
if (!IsRaw || !_buf)
|
||
{
|
||
StrPrint(tmp_buf2, "$$LK,\"%s\",A=\"AD:0x%X\"$$", tmp_buf, argv[cur_arg]);
|
||
OutStr(tmp_buf2, _buf, _dst, len, flags);
|
||
}
|
||
else
|
||
OutStr(tmp_buf, _buf, _dst, len, flags);
|
||
cur_arg++;
|
||
break;
|
||
|
||
case 'd':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
m = argv[cur_arg++];
|
||
if (m(I64) < 0)
|
||
{
|
||
flags |= PRINTF_NEG;
|
||
m = -m;
|
||
}
|
||
sp_out_dec:
|
||
if (flags & PRINTF_AUX_FORMAT_NUM)
|
||
{
|
||
if (!len)
|
||
len = 12;
|
||
d = m;
|
||
goto sp_out_eng;
|
||
}
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
comma_format_count = comma_count = 3;
|
||
do
|
||
{
|
||
tmp_buf[k++] = ModU64(&m, 10) + '0';
|
||
if (!m)
|
||
break;
|
||
if (!--comma_count)
|
||
{
|
||
tmp_buf[k++] = ',';
|
||
comma_count = 3;
|
||
}
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
sp_out_comma_num:
|
||
if (flags & PRINTF_NEG)
|
||
i = 1;
|
||
else
|
||
i = 0;
|
||
if (len < 0)
|
||
len = 0;
|
||
if (flags & PRINTF_TRUNCATE && k + i > len)
|
||
k = len - i;
|
||
if (k < 0)
|
||
k = 0;
|
||
if (flags & PRINTF_PAD_ZERO)
|
||
{
|
||
if (flags & PRINTF_NEG)
|
||
SPutChar(_dst, '-', _buf);
|
||
comma_count = (len - k - i + comma_format_count - comma_count + 1) % (comma_format_count + 1) + 1;
|
||
for (; i < len - k; i++)
|
||
{
|
||
if (!--comma_count)
|
||
{
|
||
SPutChar(_dst, ',', _buf);
|
||
comma_count = comma_format_count;
|
||
if (++i >= len - k)
|
||
break;
|
||
}
|
||
SPutChar(_dst, '0', _buf);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (; i < len - k; i++)
|
||
SPutChar(_dst, CH_SPACE, _buf);
|
||
if (flags & PRINTF_NEG)
|
||
SPutChar(_dst, '-', _buf);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
do
|
||
{
|
||
tmp_buf[k++] = ModU64(&m, 10) + '0';
|
||
if (!m)
|
||
break;
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
sp_out_num:
|
||
if (flags & PRINTF_NEG)
|
||
i = 1;
|
||
else
|
||
i = 0;
|
||
if (len < 0)
|
||
len = 0;
|
||
if (flags & PRINTF_TRUNCATE && k + i > len)
|
||
k = len - i;
|
||
if (k < 0)
|
||
k = 0;
|
||
if (flags & PRINTF_PAD_ZERO)
|
||
{
|
||
if (flags & PRINTF_NEG)
|
||
SPutChar(_dst, '-', _buf);
|
||
for (; i < len - k; i++)
|
||
SPutChar(_dst, '0', _buf);
|
||
}
|
||
else
|
||
{
|
||
for (; i < len - k; i++)
|
||
SPutChar(_dst, CH_SPACE, _buf);
|
||
if (flags & PRINTF_NEG)
|
||
SPutChar(_dst, '-', _buf);
|
||
}
|
||
}
|
||
for (i = k - 1; i >= 0; i--)
|
||
SPutChar(_dst, tmp_buf[i], _buf);
|
||
break;
|
||
|
||
case 'u':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
m = argv[cur_arg++];
|
||
goto sp_out_dec;
|
||
|
||
case 'f':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
d = argv[cur_arg++](F64);
|
||
if (d < 0)
|
||
{
|
||
flags |= PRINTF_NEG;
|
||
d = -d;
|
||
}
|
||
|
||
if (d == <EFBFBD>)
|
||
{
|
||
sp_out_inf:
|
||
if (flags & PRINTF_NEG)
|
||
i = 1;
|
||
else
|
||
i = 0;
|
||
k = 1;
|
||
if (len < 0)
|
||
len = 0;
|
||
if (flags & PRINTF_TRUNCATE && k + i > len)
|
||
k = len - i;
|
||
if (k < 0)
|
||
k = 0;
|
||
for (; i < len - k; i++)
|
||
SPutChar(_dst, CH_SPACE, _buf);
|
||
if (flags & PRINTF_NEG)
|
||
SPutChar(_dst, '-', _buf);
|
||
for (i = 0; i < k; i++)
|
||
SPutChar(_dst, '<EFBFBD>', _buf);
|
||
break;
|
||
}
|
||
|
||
sp_out_f:
|
||
if (dec_len < 0)
|
||
dec_len = 0;
|
||
n = Log10(d);
|
||
if (i = dec_len)
|
||
{
|
||
if (flags & PRINTF_COMMA)
|
||
i = i - i / 4;
|
||
if (n + i > 17)
|
||
{
|
||
n += i - 17;
|
||
d *= Pow10I64(i - n);
|
||
}
|
||
else
|
||
{
|
||
n = 0;
|
||
d *= Pow10I64(i);
|
||
}
|
||
i = dec_len;
|
||
}
|
||
else if (n > 17)
|
||
{
|
||
n -= 17;
|
||
d *= Pow10I64(-n);
|
||
}
|
||
else
|
||
n = 0;
|
||
|
||
m = Round(d);
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
comma_count = i & 3;
|
||
while (i-- && k < TMP_BUF_LEN - SLOP)
|
||
{
|
||
if (i > 2 && !comma_count--)
|
||
{
|
||
tmp_buf[k++] = ',';
|
||
comma_count = 2;
|
||
if (!--i)
|
||
break;
|
||
}
|
||
if (n)
|
||
{
|
||
n--;
|
||
tmp_buf[k++] = '0';
|
||
}
|
||
else
|
||
tmp_buf[k++] = ModU64(&m, 10) + '0';
|
||
if (!i)
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
while (i-- && k < TMP_BUF_LEN - SLOP)
|
||
{
|
||
if (n)
|
||
{
|
||
n--;
|
||
tmp_buf[k++] = '0';
|
||
}
|
||
else
|
||
tmp_buf[k++] = ModU64(&m, 10) + '0';
|
||
}
|
||
}
|
||
if (dec_len)
|
||
tmp_buf[k++] = '.';
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
comma_count = 3;
|
||
do
|
||
{
|
||
if (n)
|
||
{
|
||
n--;
|
||
tmp_buf[k++] = '0';
|
||
}
|
||
else
|
||
tmp_buf[k++] = ModU64(&m, 10) + '0';
|
||
if (!m)
|
||
break;
|
||
if (!--comma_count)
|
||
{
|
||
tmp_buf[k++] = ',';
|
||
comma_count = 3;
|
||
}
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
|
||
}
|
||
else
|
||
{
|
||
do
|
||
{
|
||
if (n)
|
||
{
|
||
n--;
|
||
tmp_buf[k++] = '0';
|
||
}
|
||
else
|
||
tmp_buf[k++] = ModU64(&m, 10) + '0';
|
||
if (!m)
|
||
break;
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
|
||
}
|
||
goto sp_out_num;
|
||
|
||
case 'e':
|
||
if (!len)
|
||
len = 12;
|
||
flags |= PRINTF_TRUNCATE;
|
||
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
d = argv[cur_arg++](F64);
|
||
if (d < 0)
|
||
{
|
||
flags |= PRINTF_NEG;
|
||
d = -d;
|
||
}
|
||
if (d == <EFBFBD>)
|
||
goto sp_out_inf;
|
||
|
||
if (d)
|
||
n = Floor(Log10(d));
|
||
else
|
||
n = 0;
|
||
sp_out_e:
|
||
d /= Pow10I64(n);
|
||
|
||
k0 = k;
|
||
for (l = 0; l < 2; l++)
|
||
{
|
||
n0 = n;
|
||
if (n < 0)
|
||
{
|
||
n = -n;
|
||
flags |= PRINTF_NEG_E;
|
||
}
|
||
else
|
||
flags &= ~PRINTF_NEG_E;
|
||
|
||
i = 3;
|
||
|
||
do tmp_buf[k++] = ModU64(&n, 10) + '0';
|
||
while (n && i--);
|
||
|
||
if (flags & PRINTF_NEG_E)
|
||
tmp_buf[k++] = '-';
|
||
tmp_buf[k++] = 'e';
|
||
dec_len = len - k - 2;
|
||
if (flags & PRINTF_NEG)
|
||
dec_len--;
|
||
|
||
if (d)
|
||
{
|
||
d1 = d + Pow10I64(-dec_len) / 2;
|
||
if (d1 < 1.0)
|
||
{
|
||
d *= 10;
|
||
n = n0 - 1;
|
||
k = k0;
|
||
}
|
||
else if (d1 >= 10)
|
||
{
|
||
d /= 10;
|
||
n = n0 + 1;
|
||
k = k0;
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
|
||
goto sp_out_f;
|
||
|
||
case 'g':
|
||
if (!len)
|
||
len = 12;
|
||
flags |= PRINTF_TRUNCATE;
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
d = argv[cur_arg++](F64);
|
||
if (d < 0)
|
||
{
|
||
flags |= PRINTF_NEG;
|
||
d = -d;
|
||
}
|
||
if (d == <EFBFBD>)
|
||
goto sp_out_inf;
|
||
if (d)
|
||
n = Floor(Log10(d));
|
||
else
|
||
n = 0;
|
||
if (n >= len - 1 - dec_len || n < -(dec_len - 1))
|
||
goto sp_out_e;
|
||
else
|
||
goto sp_out_f;
|
||
|
||
case 'n':
|
||
if (!len)
|
||
len = 12;
|
||
flags |= PRINTF_TRUNCATE;
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
d = argv[cur_arg++](F64);
|
||
if (d < 0)
|
||
{
|
||
flags |= PRINTF_NEG;
|
||
d = -d;
|
||
}
|
||
sp_out_eng: //Engineering notation
|
||
if (d == <EFBFBD>)
|
||
goto sp_out_inf;
|
||
if (d)
|
||
n = FloorI64(Floor(Log10(d)), 3);
|
||
else
|
||
n = 0;
|
||
d /= Pow10I64(n);
|
||
|
||
if (n < 0)
|
||
{
|
||
n = -n;
|
||
flags |= PRINTF_NEG_E;
|
||
}
|
||
if (flags & PRINTF_AUX_FORMAT_NUM && -24 <= n <= 24)
|
||
{
|
||
if (flags & PRINTF_QUESTION)
|
||
{
|
||
if (flags & PRINTF_NEG_E)
|
||
i = -n / 3;
|
||
else
|
||
i = n / 3;
|
||
j = 0;
|
||
}
|
||
else
|
||
{
|
||
if (flags & PRINTF_NEG_E)
|
||
j = -n - aux_format_num;
|
||
else
|
||
j = n - aux_format_num;
|
||
d *= Pow10I64(j);
|
||
i = aux_format_num / 3;
|
||
}
|
||
if (i < 0)
|
||
tmp_buf[k++] = sys_neg_pows_lets[-i];
|
||
else if (i > 0)
|
||
tmp_buf[k++] = sys_pos_pows_lets[i];
|
||
else if (len != 0)
|
||
tmp_buf[k++] = CH_SPACE;
|
||
if (!(flags & PRINTF_DECIMAL))
|
||
{
|
||
dec_len = len - k - 2;
|
||
if (flags & PRINTF_NEG)
|
||
dec_len--;
|
||
if (j > 0)
|
||
{
|
||
if (flags & PRINTF_COMMA)
|
||
dec_len -= 4 * j / 3;
|
||
else
|
||
dec_len -= j;
|
||
}
|
||
d1 = d + Pow10I64(-dec_len + 1) / 2;
|
||
if (d1 >= 10)
|
||
{
|
||
dec_len--;
|
||
if (d1 >= 100)
|
||
dec_len--;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
i = 3;
|
||
do tmp_buf[k++] = ModU64(&n, 10) + '0';
|
||
while (n && i--);
|
||
if (flags & PRINTF_NEG_E)
|
||
tmp_buf[k++] = '-';
|
||
tmp_buf[k++] = 'e';
|
||
if (!dec_len)
|
||
{
|
||
dec_len = len - k - 2;
|
||
if (flags & PRINTF_NEG)
|
||
dec_len--;
|
||
d1 = d + Pow10I64(-dec_len + 1) / 2;
|
||
if (d1 >= 10)
|
||
{
|
||
dec_len--;
|
||
if (d1 >= 100)
|
||
dec_len--;
|
||
}
|
||
}
|
||
}
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
if (len && dec_len > 0 && !(dec_len & 3))
|
||
tmp_buf[k++] = ',';
|
||
dec_len -= dec_len / 4;
|
||
}
|
||
goto sp_out_f;
|
||
|
||
case 'X':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
m = argv[cur_arg++];
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
comma_format_count = comma_count = 4;
|
||
do
|
||
{
|
||
tmp_buf[k] = m & 15 + '0';
|
||
if (tmp_buf[k] > '9')
|
||
tmp_buf[k] += 'A' - 0x3A;
|
||
k++;
|
||
m >>= 4;
|
||
if (!m)
|
||
break;
|
||
if (!--comma_count)
|
||
{
|
||
tmp_buf[k++] = ',';
|
||
comma_count = 4;
|
||
}
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
|
||
goto sp_out_comma_num;
|
||
}
|
||
else
|
||
{
|
||
do
|
||
{
|
||
tmp_buf[k] = m & 15 + '0';
|
||
if (tmp_buf[k] > '9')
|
||
tmp_buf[k] += 'A' - 0x3A;
|
||
k++;
|
||
m >>= 4;
|
||
}
|
||
while (m && k < TMP_BUF_LEN - SLOP);
|
||
|
||
goto sp_out_num;
|
||
}
|
||
|
||
case 'x':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
m = argv[cur_arg++];
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
comma_format_count = comma_count = 4;
|
||
do
|
||
{
|
||
tmp_buf[k] = m & 15 + '0';
|
||
if (tmp_buf[k] > '9')
|
||
tmp_buf[k] += 'a' - 0x3A;
|
||
k++;
|
||
m >>= 4;
|
||
if (!m)
|
||
break;
|
||
if (!--comma_count)
|
||
{
|
||
tmp_buf[k++] = ',';
|
||
comma_count = 4;
|
||
}
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
|
||
goto sp_out_comma_num;
|
||
}
|
||
else
|
||
{
|
||
do
|
||
{
|
||
tmp_buf[k] = m & 15 + '0';
|
||
if (tmp_buf[k] > '9')
|
||
tmp_buf[k] += 'a' - 0x3A;
|
||
k++;
|
||
m >>= 4;
|
||
}
|
||
while (m && k < TMP_BUF_LEN - SLOP);
|
||
|
||
goto sp_out_num;
|
||
}
|
||
|
||
case 'b':
|
||
case 'B':
|
||
if (cur_arg >= argc)
|
||
throw('StrPrint');
|
||
m = argv[cur_arg++];
|
||
if (flags & PRINTF_COMMA)
|
||
{
|
||
comma_format_count = comma_count = 4;
|
||
do
|
||
{
|
||
tmp_buf[k++] = m & 1 + '0';
|
||
m >>= 1;
|
||
if (!m)
|
||
break;
|
||
if (!--comma_count)
|
||
{
|
||
tmp_buf[k++] = ',';
|
||
comma_count = 4;
|
||
}
|
||
}
|
||
while (k < TMP_BUF_LEN - SLOP);
|
||
|
||
goto sp_out_comma_num;
|
||
}
|
||
else
|
||
{
|
||
do
|
||
{
|
||
tmp_buf[k++] = m & 1 + '0';
|
||
m >>= 1;
|
||
}
|
||
while (m && k < TMP_BUF_LEN - SLOP);
|
||
|
||
goto sp_out_num;
|
||
}
|
||
|
||
case '%':
|
||
SPutChar(_dst, '%', _buf);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
SPutChar(_dst, ch, _buf);
|
||
}
|
||
SPutChar(_dst, 0, _buf);
|
||
return buf;
|
||
}
|
||
|
||
U8 *StrPrint(U8 *dst, U8 *format, ...)
|
||
{//See $LK,"StrPrintJoin",A="MN:StrPrintJoin"$().
|
||
return StrPrintJoin(dst, format, argc, argv);
|
||
}
|
||
|
||
U8 *CatPrint(U8 *_dst, U8 *format, ...)
|
||
{//StrCat(). See $LK,"StrPrintJoin",A="MN:StrPrintJoin"$().
|
||
U8 *dst = _dst;
|
||
|
||
while (*dst)
|
||
dst++;
|
||
StrPrintJoin(dst, format, argc, argv);
|
||
|
||
return _dst;
|
||
}
|
||
|
||
U0 Print(U8 *format, ...)
|
||
{//$LK,"Print(\"\") Format Strings",A="FI:::/Doc/Print.DD"$. See $LK,"StrPrintJoin",A="MN:StrPrintJoin"$().
|
||
//Don't use this. $LK,"See Print() shortcut.",A="FF:::/Doc/ZealC.DD,DemoZealC"$
|
||
U8 *buf = StrPrintJoin(NULL, format, argc, argv);
|
||
|
||
PutS(buf);//Don't use PutS(). $LK,"See Print() shortcut.",A="FF:::/Doc/ZealC.DD,DemoZealC"$
|
||
Free(buf);
|
||
}
|
||
|
||
U8 *MStrPrint(U8 *format, ...)
|
||
{//MAlloc StrPrint. See $LK,"StrPrintJoin",A="MN:StrPrintJoin"$().
|
||
U8 *res, *buf = StrPrintJoin(NULL, format, argc, argv);
|
||
|
||
res = StrNew(buf);
|
||
Free(buf);
|
||
|
||
return res;
|
||
}
|
||
|
||
U0 PrintErr(U8 *format, ...)
|
||
{//Print "Err:" and message in blinking red.
|
||
U8 *buf = StrPrintJoin(NULL, format, argc, argv);
|
||
|
||
GetOutOfDollar;
|
||
"%,p <20> %,p <20> %,p <20> %,p " ST_ERR_ST "%s", Caller, Caller(2), Caller(3), Caller(4), buf;
|
||
Free(buf);
|
||
}
|
||
|
||
U0 PrintWarn(U8 *format, ...)
|
||
{//Print "Warn:" and message in blinking red.
|
||
U8 *buf = StrPrintJoin(NULL, format, argc, argv);
|
||
|
||
GetOutOfDollar;
|
||
"%,p <20> %,p <20> %,p <20> %,p " ST_WARN_ST "%s", Caller, Caller(2), Caller(3), Caller(4), buf;
|
||
Free(buf);
|
||
}
|