From 511685325d9653101a539b7d5bcea75a6b9c4110 Mon Sep 17 00:00:00 2001 From: cfif Date: Tue, 30 Sep 2025 15:52:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9?= =?UTF-8?q?=D1=81=D1=8B=20=D0=B8=20=D0=B4=D1=80=D0=B0=D0=B9=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/LoggerInterface.h | 160 ++++++ Src/LoggerLevelNames.c | 25 + Src/LoggerPrintf.c | 1219 ++++++++++++++++++++++++++++++++++++++++ modular.json | 17 + 4 files changed, 1421 insertions(+) create mode 100644 Inc/LoggerInterface.h create mode 100644 Src/LoggerLevelNames.c create mode 100644 Src/LoggerPrintf.c create mode 100644 modular.json diff --git a/Inc/LoggerInterface.h b/Inc/LoggerInterface.h new file mode 100644 index 0000000..0ae2e99 --- /dev/null +++ b/Inc/LoggerInterface.h @@ -0,0 +1,160 @@ +// +// Created by xemon on 13.11.22. +// + +#ifndef UVEOS_ON_NATION_LOGGERINTERFACE_H +#define UVEOS_ON_NATION_LOGGERINTERFACE_H + +#include +#include "stddef.h" +#include "stdint.h" +#include "stdbool.h" + +typedef enum { + LOGLEVEL_FATAL, + LOGLEVEL_ERROR, + LOGLEVEL_WARN, + LOGLEVEL_INFO, + LOGLEVEL_DEBUG, + LOGLEVEL_TRACE, +} eLoggerLevel; + +typedef void (*LoggerGenericMethod)( + void *env, + const char *authorStatic, + const uint8_t authorLen, + eLoggerLevel loglevel, + char *msg, + uint16_t msgLen, + bool complete +); + +extern tStringStatic LOGGER_LEVEL_NAMES[]; + +typedef struct { + void *env; + LoggerGenericMethod logging; +} tLoggerInterface; + + +void LoggerPrintf( + tLoggerInterface *logger, + const char *authorStatic, + const uint8_t authorLen, + eLoggerLevel loglevel, + bool complete, + const char *fmt, + ... +); + +#ifndef LOGGER_LEVEL_INFO + +#define LOGGER_LEVEL_INFO 1 + +#endif + +#ifndef LOGGER_LEVEL_TRACE + +#define LOGGER_LEVEL_TRACE 0 + +#endif + +#ifndef LOGGER_LEVEL_ERROR + +#define LOGGER_LEVEL_ERROR 1 + +#endif + +#define LoggerFormat + +#if LOGGER_LEVEL_ERROR +#define LoggerErrorStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, sizeof(MSG)-1,true); } +#define LoggerCnErrorStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, sizeof(MSG)-1,false); } +#define LoggerError(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, SIZE,true); } +#define LoggerCnError(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, SIZE,false); } +#define LoggerFormatError(LOGGER, AUTHOR, FMT_MSG, ...) if(LOGGER){ LoggerPrintf(LOGGER,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR,true, FMT_MSG, __VA_ARGS__); } + +#define LoggerErrorStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, sizeof(MSG)-1,true); } +#define LoggerCnErrorStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, sizeof(MSG)-1,false); } +#define LoggerError(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, SIZE,true); } +#define LoggerCnError(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR, MSG, SIZE,false); } +#define LoggerFormatError(LOGGER, AUTHOR, FMT_MSG, ...) if(LOGGER){ LoggerPrintf(LOGGER,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_ERROR,true, FMT_MSG, __VA_ARGS__); } + +#else +#define LoggerStrErrorStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrCnErrorStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrError(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrCnError(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrFormatError(LOGGER, AUTHOR, FMT_MSG, ...) // невыводим + + +#define LoggerStrErrorStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrCnErrorStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrError(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrCnError(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrFormatError(LOGGER, AUTHOR, FMT_MSG, ...) // невыводим + +#endif + +#if LOGGER_LEVEL_INFO +#define LoggerInfoRaw(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_INFO, MSG, SIZE, true); } + +#define LoggerInfoStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_INFO, MSG, sizeof(MSG)-1,true); } +#define LoggerCnInfoStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_INFO, MSG, sizeof(MSG)-1,false); } +#define LoggerInfo(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_INFO, MSG, SIZE,true); } +#define LoggerCnInfo(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_INFO, MSG, SIZE,false); } +#define LoggerFormatInfo(LOGGER, AUTHOR, FMT_MSG, ...) if(LOGGER){ LoggerPrintf(LOGGER,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_INFO,true, FMT_MSG, __VA_ARGS__); } + + +#define LoggerStrInfoStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,strlen(AUTHOR),LOGLEVEL_INFO, MSG, sizeof(MSG)-1,true); } +#define LoggerStrCnInfoStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,strlen(AUTHOR),LOGLEVEL_INFO, MSG, sizeof(MSG)-1,false); } +#define LoggerStrInfo(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,strlen(AUTHOR),LOGLEVEL_INFO, MSG, SIZE,true); } +#define LoggerStrCnInfo(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,strlen(AUTHOR),LOGLEVEL_INFO, MSG, SIZE,false); } +#define LoggerStrFormatInfo(LOGGER, AUTHOR, FMT_MSG, ...) if(LOGGER){ LoggerPrintf(LOGGER,AUTHOR,strlen(AUTHOR),LOGLEVEL_INFO,true, FMT_MSG, __VA_ARGS__); } + +#else +#define LoggerInfoStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerCnInfoStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerInfo(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerCnInfo(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerFormatInfo(LOGGER, AUTHOR, FMT_MSG, ...) // невыводим + +#define LoggerStrInfoStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrCnInfoStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrInfo(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrCnInfo(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrFormatInfo(LOGGER, AUTHOR, FMT_MSG, ...) // невыводим + +#endif + + +#if LOGGER_LEVEL_TRACE +#define LoggerCnTraceStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, sizeof(MSG)-1,false); } +#define LoggerTraceStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, sizeof(MSG)-1,true); } +#define LoggerTrace(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, SIZE,true); } +#define LoggerCnTrace(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, SIZE,false); } +#define LoggerFormatTrace(LOGGER, AUTHOR, FMT_MSG, ...) if(LOGGER){ LoggerPrintf(LOGGER,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE,true, FMT_MSG, __VA_ARGS__); } + +#define LoggerStrCnTraceStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, sizeof(MSG)-1,false); } +#define LoggerStrTraceStatic(LOGGER, AUTHOR, MSG) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, sizeof(MSG)-1,true); } +#define LoggerStrTrace(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, SIZE,true); } +#define LoggerStrCnTrace(LOGGER, AUTHOR, MSG, SIZE) if(LOGGER){ (LOGGER)->logging((LOGGER)->env,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE, MSG, SIZE,false); } +#define LoggerStrFormatTrace(LOGGER, AUTHOR, FMT_MSG, ...) if(LOGGER){ LoggerPrintf(LOGGER,AUTHOR,sizeof(AUTHOR)-1,LOGLEVEL_TRACE,true, FMT_MSG, __VA_ARGS__); } + +#else +#define LoggerCnTraceStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerTraceStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerTrace(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerCnTrace(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerFormatTrace(LOGGER, AUTHOR, FMT_MSG, ...) // невыводим + + +#define LoggerStrCnTraceStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrTraceStatic(LOGGER, AUTHOR, MSG) // невыводим +#define LoggerStrTrace(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrCnTrace(LOGGER, AUTHOR, MSG, SIZE) // невыводим +#define LoggerStrFormatTrace(LOGGER, AUTHOR, FMT_MSG, ...) // невыводим + +#endif + +#endif //UVEOS_ON_NATION_LOGGERINTERFACE_H diff --git a/Src/LoggerLevelNames.c b/Src/LoggerLevelNames.c new file mode 100644 index 0000000..9d77f18 --- /dev/null +++ b/Src/LoggerLevelNames.c @@ -0,0 +1,25 @@ +// +// Created by xemon on 13.11.22. +// + +#include "LoggerInterface.h" + +tStringStatic LOGGER_LEVEL_NAMES[] = { + StringStaticInit("FATAL"), + StringStaticInit("ERROR"), + StringStaticInit("WARN"), + StringStaticInit("INFO"), + StringStaticInit("DEBUG"), + StringStaticInit("TRACE"), +}; + +void LoggerInterfaceLogFormat(void *env, + char *authorStatic, + uint8_t authorLen, + eLoggerLevel loglevel, + char *msg, + uint16_t msgLen, + bool complete +) { + +} \ No newline at end of file diff --git a/Src/LoggerPrintf.c b/Src/LoggerPrintf.c new file mode 100644 index 0000000..7d89f35 --- /dev/null +++ b/Src/LoggerPrintf.c @@ -0,0 +1,1219 @@ +#include +#include +#include +#include +#include +#include "LoggerInterface.h" + +#define FETCH_BYTE(p) (*(unsigned char*)(p)) +/* Max number conversion buffer length: a long in base 2, plus NUL byte. */ +#define MAXNBUF (sizeof(long) * 8 + 1) + +static unsigned char *ksprintn(unsigned char *buf, unsigned long v, unsigned char base, + int width, unsigned char *lp); + +static unsigned char mkhex(unsigned char ch); + +#define ARCH_HAVE_FPU 1 + +#if ARCH_HAVE_FPU + +static int cvt_f(double number, int prec, int sharpflag, unsigned char *negp, + unsigned char fmtch, unsigned char *startp, unsigned char *endp); + +#endif + +int stream_logger_vprintf(tLoggerInterface *logger, char const *fmt, va_list ap) { + //#define PUTC(c) { putchar(stream,(unsigned char)(c)); ++retval; } +#define PUTC(c) { char p = c; (logger)->logging((logger)->env, NULL, 0, 0, &p, 1, false); ++retval; } + + + unsigned char nbuf[MAXNBUF], padding, *q; + const unsigned char *s; + unsigned char c, base, lflag, ladjust, sharpflag, neg, dot, size; + int16_t n, width, dwidth, retval, uppercase, extrazeros, sign; + unsigned long ul; + + if (!logger) + return 0; + if (!fmt) + fmt = "(null)\n"; + + retval = 0; + for (;;) { + while ((c = FETCH_BYTE (fmt++)) != '%') { + if (!c) + return retval; + PUTC (c); + } + padding = ' '; + width = 0; + extrazeros = 0; + lflag = 0; + ladjust = 0; + sharpflag = 0; + neg = 0; + sign = 0; + dot = 0; + uppercase = 0; + dwidth = -1; + reswitch: + switch (c = FETCH_BYTE (fmt++)) { + case '.': + dot = 1; + padding = ' '; + dwidth = 0; + goto reswitch; + + case '#': + sharpflag = 1; + goto reswitch; + + case '+': + sign = -1; + goto reswitch; + + case '-': + ladjust = 1; + goto reswitch; + + case '%': PUTC (c); + break; + + case '*': + if (!dot) { + width = va_arg (ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + } else { + dwidth = va_arg (ap, int); + } + goto reswitch; + + case '0': + if (!dot) { + padding = '0'; + goto reswitch; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (n = 0;; ++fmt) { + n = n * 10 + c - '0'; + c = FETCH_BYTE (fmt); + if (c < '0' || c > '9') + break; + } + if (dot) + dwidth = n; + else + width = n; + goto reswitch; + + case 'b': + ul = va_arg (ap, int); + s = va_arg (ap, const unsigned char*); + q = ksprintn(nbuf, ul, *s++, -1, 0); + while (*q) PUTC (*q--); + + if (!ul) + break; + size = 0; + while (*s) { + n = *s++; + if ((char) (ul >> (n - 1)) & 1) { + PUTC (size ? ',' : '<'); + for (; (n = *s) > ' '; ++s) PUTC (n); + size = 1; + } else + while (*s > ' ') + ++s; + } + if (size) PUTC ('>'); + break; + + case 'c': + if (!ladjust && width > 0) + while (width--) PUTC (' '); + + PUTC (va_arg(ap, int)); + + if (ladjust && width > 0) + while (width--) PUTC (' '); + break; + + case 'D': + s = va_arg (ap, const unsigned char*); + if (!width) + width = 16; + if (sharpflag) + padding = ':'; + while (width--) { + c = *s++; + PUTC (mkhex(c >> 4)); + PUTC (mkhex(c)); + if (width) PUTC (padding); + } + break; + + case 'd': + ul = lflag ? va_arg (ap, long) : va_arg (ap, int); + if (!sign) sign = 1; + base = 10; + goto number; + + case 'l': + lflag = 1; + goto reswitch; + + case 'o': + ul = lflag ? va_arg (ap, unsigned long) : + va_arg (ap, unsigned int); + base = 8; + goto nosign; + + case 'p': + ul = (size_t) va_arg (ap, void*); + if (!ul) { + s = (const unsigned char *) "(nil)"; + goto const_string; + } + base = 16; + sharpflag = (width == 0); + goto nosign; + + case 'n': + ul = lflag ? va_arg (ap, unsigned long) : + sign ? (unsigned long) va_arg (ap, int) : + va_arg (ap, unsigned int); + base = 10; + goto number; + + case 'S': +#if __AVR__ + s = va_arg (ap, const unsigned char*); + if (! s) + s = (const unsigned char*) "(null)"; + const_string: + n = 0; + if (! dot) + while (FETCH_BYTE (s+n)) + ++n; + else + while (n 0) + while (width--) + PUTC (' '); + while (n--) + PUTC (FETCH_BYTE (s++)); + if (ladjust && width > 0) + while (width--) + PUTC (' '); + break; +#endif /* LY: AVR, and no break here! */ + + case 's': + s = va_arg (ap, unsigned char*); +#ifdef __AVR__ + if (! s) { + s = (const unsigned char*) "(null)"; + goto const_string; + } +#else + if (!s) + s = (const unsigned char *) "(null)"; + const_string: +#endif + if (!dot) + n = strlen(s); + else + for (n = 0; n < dwidth && s[n]; n++) + continue; + + width -= n; + + if (!ladjust && width > 0) + while (width--) PUTC (' '); + while (n--) PUTC (*s++); + if (ladjust && width > 0) + while (width--) PUTC (' '); + break; + + case 'r': + /* Saturated counters. */ + base = 10; + if (lflag) { + ul = va_arg (ap, unsigned long); + if (ul == -1) { + cnt_unknown: + if (ladjust) PUTC ('-'); + while (--width > 0) PUTC (' '); + if (!ladjust) PUTC ('-'); + break; + } + if (ul >= -2) { + ul = -3; + neg = '>'; + goto nosign; + } + } else { + ul = va_arg (ap, unsigned int); + if (ul == (unsigned short) -1) + goto cnt_unknown; + if (ul >= (unsigned short) -2) { + ul = (unsigned short) -3; + neg = '>'; + goto nosign; + } + } + goto nosign; + + case 'u': + ul = lflag ? va_arg (ap, unsigned long) : + va_arg (ap, unsigned int); + base = 10; + goto nosign; + + case 'x': + case 'X': + ul = lflag ? va_arg (ap, unsigned long) : + va_arg (ap, unsigned int); + base = 16; + uppercase = (c == 'X'); + goto nosign; + case 'z': + case 'Z': + ul = lflag ? va_arg (ap, unsigned long) : + sign ? (unsigned long) va_arg (ap, int) : + va_arg (ap, unsigned int); + base = 16; + uppercase = (c == 'Z'); + goto number; + + nosign: + sign = 0; + number: + if (sign && ((long) ul != 0L)) { + if ((long) ul < 0L) { + neg = '-'; + ul = -(long) ul; + } else if (sign < 0) + neg = '+'; + } + if (dwidth >= (int) sizeof(nbuf)) { + extrazeros = dwidth - sizeof(nbuf) + 1; + dwidth = sizeof(nbuf) - 1; + } + s = ksprintn(nbuf, ul, base, dwidth, &size); + if (sharpflag && ul != 0) { + if (base == 8) + size++; + else if (base == 16) + size += 2; + } + if (neg) + size++; + + if (!ladjust && width && padding == ' ' && + (width -= size) > 0) + do { + PUTC (' '); + } while (--width > 0); + + if (neg) PUTC (neg); + + if (sharpflag && ul != 0) { + if (base == 8) { + PUTC ('0'); + } else if (base == 16) { + PUTC ('0'); + PUTC (uppercase ? 'X' : 'x'); + } + } + + if (extrazeros) + do { + PUTC ('0'); + } while (--extrazeros > 0); + + if (!ladjust && width && (width -= size) > 0) + do { + PUTC (padding); + } while (--width > 0); + + for (; *s; --s) { + if (uppercase && *s >= 'a' && *s <= 'z') { + PUTC (*s + 'A' - 'a'); + } else { + PUTC (*s); + } + } + + if (ladjust && width && (width -= size) > 0) + do { + PUTC (' '); + } while (--width > 0); + break; +#if ARCH_HAVE_FPU + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': { + double d = va_arg (ap, double); + /* + * don't do unrealistic precision; just pad it with + * zeroes later, so buffer size stays rational. + */ + if (dwidth > DBL_DIG) { + if ((c != 'g' && c != 'G') || sharpflag) + extrazeros = dwidth - DBL_DIG; + dwidth = DBL_DIG; + } else if (dwidth == -1) { + dwidth = (lflag ? DBL_DIG : FLT_DIG); + } + /* + * softsign avoids negative 0 if d is < 0 and + * no significant digits will be shown + */ + if (d < 0) { + neg = 1; + d = -d; + } + /* + * cvt may have to round up past the "start" of the + * buffer, i.e. ``intf("%.2f", (double)9.999);''; + * if the first char isn't NULL, it did. + */ + if (isnan (d) || isinf (d)) { + strcpy(nbuf, isnan (d) ? "NaN" : "Inf"); + size = 3; + extrazeros = 0; + s = nbuf; + } else { + *nbuf = 0; + size = cvt_f(d, dwidth, sharpflag, &neg, c, + nbuf, nbuf + sizeof(nbuf) - 1); + if (*nbuf) { + s = nbuf; + nbuf[size] = 0; + } else { + s = nbuf + 1; + nbuf[size + 1] = 0; + } + } + if (neg) + size++; + if (!ladjust && width && padding == ' ' && + (width -= size) > 0) + do { + PUTC (' '); + } while (--width > 0); + + if (neg) PUTC ('-'); + + if (!ladjust && width && (width -= size) > 0) + do { + PUTC (padding); + } while (--width > 0); + + for (; *s; ++s) { + if (extrazeros && (*s == 'e' || *s == 'E')) + do { + PUTC ('0'); + } while (--extrazeros > 0); + + PUTC (*s); + } + if (extrazeros) + do { + PUTC ('0'); + } while (--extrazeros > 0); + + if (ladjust && width && (width -= size) > 0) + do { + PUTC (' '); + } while (--width > 0); + break; + } +#endif + default: PUTC ('%'); + if (lflag) PUTC ('l'); + PUTC (c); + break; + } + } +} + +/* + * Put a NUL-terminated ASCII number (base <= 16) in a buffer in reverse + * order; return an optional length and a pointer to the last character + * written in the buffer (i.e., the first character of the string). + * The buffer pointed to by `nbuf' must have length >= MAXNBUF. + */ +static unsigned char * +ksprintn(unsigned char *nbuf, unsigned long ul, unsigned char base, int width, + unsigned char *lenp) { + unsigned char *p; + + p = nbuf; + *p = 0; + for (;;) { + *++p = mkhex(ul % base); + ul /= base; + if (--width > 0) + continue; + if (!ul) + break; + } + if (lenp) + *lenp = p - nbuf; + return (p); +} + +static unsigned char +mkhex(unsigned char ch) { + ch &= 15; + if (ch > 9) + return ch + 'a' - 10; + return ch + '0'; +} + +#if ARCH_HAVE_FPU + +static unsigned char * +cvtround_f(double fract, int *exp, unsigned char *start, unsigned char *end, unsigned char ch, + unsigned char *negp) { + double tmp; + + if (fract) { + modf(fract * 10, &tmp); + } else { + tmp = ch - '0'; + } + if (tmp > 4) { + for (;; --end) { + if (*end == '.') { + --end; + } + if (++*end <= '9') { + break; + } + *end = '0'; + if (end == start) { + if (exp) { /* e/E; increment exponent */ + *end = '1'; + ++*exp; + } else { /* f; add extra digit */ + *--end = '1'; + --start; + } + break; + } + } + } else if (*negp) { + /* + * ``"%.3f", (double)-0.0004'' gives you a negative 0. + */ + for (;; --end) { + if (*end == '.') { + --end; + } + if (*end != '0') { + break; + } + if (end == start) { + *negp = 0; + } + } + } + return start; +} + +static unsigned char * +exponent(unsigned char *p, int exp, unsigned char fmtch) { + unsigned char expbuf[8], *t; + + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } else { + *p++ = '+'; + } + t = expbuf + sizeof(expbuf); + if (exp > 9) { + do { + *--t = exp % 10 + '0'; + } while ((exp /= 10) > 9); + *--t = exp + '0'; + for (; t < expbuf + sizeof(expbuf); *p++ = *t++) + continue; + } else { + *p++ = '0'; + *p++ = exp + '0'; + } + return p; +} + +static int +cvt_f(double number, int prec, int sharpflag, unsigned char *negp, unsigned char fmtch, + unsigned char *startp, unsigned char *endp) { + unsigned char *p, *t; + double fract; + int dotrim, expcnt, gformat; + double integer, tmp; + + expcnt = 0; + dotrim = expcnt = gformat = 0; + fract = modf(number, &integer); + + /* + * get an extra slot for rounding + */ + t = ++startp; + + /* + * get integer portion of number; put into the end of the buffer; the + * .01 is added for modf (356.0 / 10, &integer) returning .59999999... + */ + for (p = endp - 1; integer; ++expcnt) { + tmp = modf(integer / 10, &integer); + *p-- = (int) ((tmp + .01) * 10) + '0'; + } + switch (fmtch) { + case 'f': + /* reverse integer into beginning of buffer */ + if (expcnt) { + for (; ++p < endp; *t++ = *p); + } else { + *t++ = '0'; + } + + /* + * if precision required or alternate flag set, add in a + * decimal point. + */ + if (prec || sharpflag) { + *t++ = '.'; + } + + /* + * if requires more precision and some fraction left + */ + if (fract) { + if (prec) { + do { + fract = modf(fract * 10, &tmp); + *t++ = (int) tmp + '0'; + } while (--prec && fract); + } + if (fract) { + startp = cvtround_f(fract, 0, startp, + t - 1, '0', negp); + } + } + for (; prec--; *t++ = '0'); + break; + case 'e': + case 'E': + eformat: + if (expcnt) { + *t++ = *++p; + if (prec || sharpflag) { + *t++ = '.'; + } + + /* + * if requires more precision and some integer left + */ + for (; prec && ++p < endp; --prec) { + *t++ = *p; + } + + /* + * if done precision and more of the integer component, + * round using it; adjust fract so we don't re-round + * later. + */ + if (!prec && ++p < endp) { + fract = 0; + startp = cvtround_f(0, &expcnt, startp, + t - 1, *p, negp); + } + /* + * adjust expcnt for digit in front of decimal + */ + --expcnt; + } + /* + * until first fractional digit, decrement exponent + */ + else if (fract) { + /* + * adjust expcnt for digit in front of decimal + */ + for (expcnt = -1;; --expcnt) { + fract = modf(fract * 10, &tmp); + if (tmp) { + break; + } + } + *t++ = (int) tmp + '0'; + if (prec || sharpflag) { + *t++ = '.'; + } + } else { + *t++ = '0'; + if (prec || sharpflag) { + *t++ = '.'; + } + } + /* + * if requires more precision and some fraction left + */ + if (fract) { + if (prec) { + do { + fract = modf(fract * 10, &tmp); + *t++ = (int) tmp + '0'; + } while (--prec && fract); + } + if (fract) { + startp = cvtround_f(fract, &expcnt, startp, + t - 1, '0', negp); + } + } + /* + * if requires more precision + */ + for (; prec--; *t++ = '0'); + + /* + * unless alternate flag, trim any g/G format trailing 0's + */ + if (gformat && !sharpflag) { + while (t > startp && *--t == '0'); + if (*t == '.') { + --t; + } + ++t; + } + t = exponent(t, expcnt, fmtch); + break; + case 'g': + case 'G': + /* + * a precision of 0 is treated as a precision of 1 + */ + if (!prec) { + ++prec; + } + + /* + * ``The style used depends on the value converted; style e + * will be used only if the exponent resulting from the + * conversion is less than -4 or greater than the precision.'' + * -- ANSI X3J11 + */ + if (expcnt > prec || (!expcnt && fract && fract < .0001)) { + /* + * g/G format counts "significant digits, not digits of + * precision; for the e/E format, this just causes an + * off-by-one problem, i.e. g/G considers the digit + * before the decimal point significant and e/E doesn't + * count it as precision. + */ + --prec; + fmtch -= 2; /* G->E, g->e */ + gformat = 1; + goto eformat; + } + /* + * reverse integer into beginning of buffer, + * note, decrement precision + */ + if (expcnt) { + for (; ++p < endp; *t++ = *p, --prec); + } else { + *t++ = '0'; + } + /* + * if precision required or alternate flag set, add in a + * decimal point. If no digits yet, add in leading 0. + */ + if (prec || sharpflag) { + dotrim = 1; + *t++ = '.'; + } else { + dotrim = 0; + } + /* + * if requires more precision and some fraction left + */ + while (prec && fract) { + fract = modf(fract * 10, &tmp); + *t++ = (int) tmp + '0'; + prec--; + } + if (fract) { + startp = cvtround_f(fract, 0, startp, t - 1, '0', negp); + } + /* + * alternate format, adds 0's for precision, else trim 0's + */ + if (sharpflag) { + for (; prec--; *t++ = '0'); + } else if (dotrim) { + while (t > startp && *--t == '0'); + if (*t != '.') { + ++t; + } + } + } + return (t - startp); +} + +#endif /* ARCH_HAVE_FPU */ + + +void LoggerPrintf( + tLoggerInterface *logger, + const char *authorStatic, + const uint8_t authorLen, + eLoggerLevel loglevel, + bool complete, + const char *fmt, + ... +) { + +// va_list args; +// int err; +// +// LoggerCnInfo(logger, "ss", "", 0); +// +// va_start (args, fmt); +// err = stream_logger_vprintf(logger, fmt, args); +// va_end (args); +// +// LoggerInfo(logger, "ss", "", 0); + + char str[512]; + + int result; + va_list args; + + va_start(args, fmt); + result = vsprintf(str, fmt, args); + va_end(args); + + logger->logging(logger->env, authorStatic, authorLen, loglevel, str, result, complete); +} + +#ifdef TEST +/* + * Testing vprintf(3). + */ +#undef printf +#undef fclose +#undef fflush +#undef vprintf +#undef getchar +#undef putchar +#undef gets +#undef puts +#undef feof +#define snprintf snprintf_tmp +#define vsnprintf vsnprintf_tmp +#include +#undef snprintf +#undef vsnprintf + +#ifndef UCHAR_MAX +#define UCHAR_MAX ((unsigned char) -1) +#endif +#ifndef USHRT_MAX +#define USHRT_MAX ((unsigned short) -1) +#endif + +#define fputs(s,f) printstring (s) +#define puts(s) { printstring (s); write (1, "\n", 1); } + +unsigned write (int fd, const void *buf, unsigned count); + +static void +printchar (stream_t *stream, short ch) +{ + write (1, &ch, 1); +} + +static void +printstring (const char *str) +{ + write (1, str, strlen (str)); +} + +int +printf (const char *fmt, ...) +{ + static stream_interface_t output_interface = { + (void (*) (stream_t*, short)) printchar, + 0, 0, + }; + stream_t output = { &output_interface }; + va_list args; + int err; + + va_start (args, fmt); + err = stream_vprintf (&output, fmt, args); + va_end (args); + return err; +} + +static void rfg1 (void); +static void rfg2 (void); +static void rfg3 (void); + +static void fmtchk (const char *fmt) +{ + (void)fputs (fmt, stdout); + (void)printf (":\t`"); + (void)printf (fmt, 0x12); + (void)printf ("'\n"); +} + +static void fmtst1chk (const char *fmt) +{ + (void)fputs (fmt, stdout); + (void)printf (":\t`"); + (void)printf (fmt, 4, 0x12); + (void)printf ("'\n"); +} + +static void fmtst2chk (const char *fmt) +{ + (void)fputs (fmt, stdout); + (void)printf (":\t`"); + (void)printf (fmt, 4, 4, 0x12); + (void)printf ("'\n"); +} + +/* This page is covered by the following copyright: */ + +/* (C) Copyright C E Chew + * + * Feel free to copy, use and distribute this software provided: + * + * 1. you do not pretend that you wrote it + * 2. you leave this copyright notice intact. + */ + +/* + * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans. + */ + +#define DEC -123 +#define INT 255 +#define UNS (~0) + +/* Formatted Output Test + * + * This exercises the output formatting code. + */ + +static void fp_test (void) +{ + int i, j, k, l; + char buf[7]; + char *prefix = buf; + char tp[20]; + + puts ("\nFormatted output test"); + printf ("prefix 6d 6o 6x 6X 6u\n"); + strcpy (prefix, "%"); + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + for (l = 0; l < 2; l++) { + strcpy (prefix, "%"); + if (i == 0) + strcat (prefix, "-"); + if (j == 0) + strcat (prefix, "+"); + if (k == 0) + strcat (prefix, "#"); + if (l == 0) + strcat (prefix, "0"); + printf ("%5s |", prefix); + strcpy (tp, prefix); + strcat (tp, "6d |"); + printf (tp, DEC); + strcpy (tp, prefix); + strcat (tp, "6o |"); + printf (tp, INT); + strcpy (tp, prefix); + strcat (tp, "6x |"); + printf (tp, INT); + strcpy (tp, prefix); + strcat (tp, "6X |"); + printf (tp, INT); + strcpy (tp, prefix); + strcat (tp, "6u |"); + printf (tp, UNS); + printf ("\n"); + } + } + } + } + printf ("%10s\n", (char *)0); + printf ("%-10s\n", (char *)0); +} + +int main () +{ + static char shortstr[] = "Hi, Z."; + static char longstr[] = "Good morning, Doctor Chandra. This is Hal. \ +I am ready for my first lesson today."; + int result = 0; + + fmtchk ("%.4x"); + fmtchk ("%04x"); + fmtchk ("%4.4x"); + fmtchk ("%04.4x"); + fmtchk ("%4.3x"); + fmtchk ("%04.3x"); + + fmtst1chk ("%.*x"); + fmtst1chk ("%0*x"); + fmtst2chk ("%*.*x"); + fmtst2chk ("%0*.*x"); + + printf ("binary format:\t\"%b\"\n", 55, "\20\7b7\6b6\5b5\4b4\3b3\2b2\1b1"); + printf ("nil pointer (padded):\t\"%10p\"\n", (void *)0); + + printf ("decimal negative:\t\"%d\"\n", -2345); + printf ("octal negative:\t\"%o\"\n", -2345); + printf ("hex negative:\t\"%x\"\n", -2345); + printf ("long decimal number:\t\"%ld\"\n", -123456L); + printf ("long octal negative:\t\"%lo\"\n", -2345L); + printf ("long unsigned decimal number:\t\"%lu\"\n", -123456L); + printf ("zero-padded LDN:\t\"%010ld\"\n", -123456L); + printf ("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456L); + printf ("space-padded LDN:\t\"%10ld\"\n", -123456L); + printf ("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L); + + printf ("zero-padded string:\t\"%010s\"\n", shortstr); + printf ("left-adjusted Z string:\t\"%-010s\"\n", shortstr); + printf ("space-padded string:\t\"%10s\"\n", shortstr); + printf ("left-adjusted S string:\t\"%-10s\"\n", shortstr); + printf ("null string:\t\"%s\"\n", (char *)0); + printf ("limited string:\t\"%.22s\"\n", longstr); + + printf ("e-style >= 1:\t\"%e\"\n", 12.34); + printf ("e-style >= .1:\t\"%e\"\n", 0.1234); + printf ("e-style < .1:\t\"%e\"\n", 0.001234); + printf ("e-style big:\t\"%.60e\"\n", 1e20); + printf ("e-style == .1:\t\"%e\"\n", 0.1); + printf ("f-style >= 1:\t\"%f\"\n", 12.34); + printf ("f-style >= .1:\t\"%f\"\n", 0.1234); + printf ("f-style < .1:\t\"%f\"\n", 0.001234); + printf ("g-style >= 1:\t\"%g\"\n", 12.34); + printf ("g-style >= .1:\t\"%g\"\n", 0.1234); + printf ("g-style < .1:\t\"%g\"\n", 0.001234); + printf ("g-style big:\t\"%.60g\"\n", 1e20); + + printf (" %6.5f\n", .099999999860301614); + printf (" %6.5f\n", .1); + printf ("x%5.4fx\n", .5); + + printf ("%#03x\n", 1); + + printf ("something really insane: %.10000f\n", 1.0); + + { + double d = FLT_MIN; + int niter = 17; + + while (niter-- != 0) + printf ("%.17e\n", d / 2); + fflush (stdout); + } + + printf ("%15.5e\n", 4.9406564584124654e-324); + +#define FORMAT "|%12.4f|%12.4e|%12.4g|\n" + printf (FORMAT, 0.0, 0.0, 0.0); + printf (FORMAT, 1.0, 1.0, 1.0); + printf (FORMAT, -1.0, -1.0, -1.0); + printf (FORMAT, 100.0, 100.0, 100.0); + printf (FORMAT, 1000.0, 1000.0, 1000.0); + printf (FORMAT, 10000.0, 10000.0, 10000.0); + printf (FORMAT, 12345.0, 12345.0, 12345.0); + printf (FORMAT, 100000.0, 100000.0, 100000.0); + printf (FORMAT, 123456.0, 123456.0, 123456.0); +#undef FORMAT + + { + char buf[20]; + char buf2[512]; + + printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n", + snprintf (buf, sizeof (buf), "%30s", "foo"), (int)sizeof (buf), + buf); + printf ("snprintf (\"%%.999999u\", 10) == %d\n", + snprintf (buf2, sizeof (buf2), "%.999999u", 10)); + } + + fp_test (); + + printf ("%e should be 1.234568e+06\n", 1234567.8); + printf ("%f should be 1234567.800000\n", 1234567.8); + printf ("%g should be 1.23457e+06\n", 1234567.8); + printf ("%g should be 123.456\n", 123.456); + printf ("%g should be 1e+06\n", 1000000.0); + printf ("%g should be 10\n", 10.0); + printf ("%g should be 0.02\n", 0.02); + + { + char buf[200]; + + snprintf (buf, sizeof(buf), "%*s%*s%*s", -1, "one", -20, "two", -30, "three"); + + result |= strcmp (buf, + "onetwo three "); + + puts (result != 0 ? "Test failed!" : "Test ok."); + } +#if 0 + { + char buf[200]; + + snprintf (buf, sizeof(buf), "%07Lo", 040000000000ll); + printf ("sprintf (buf, \"%%07Lo\", 040000000000ll) = %s", buf); + + if (strcmp (buf, "40000000000") != 0) { + result = 1; + fputs ("\tFAILED", stdout); + } + puts (""); + } + + printf ("printf (\"%%hhu\", %u) = %hhu\n", UCHAR_MAX + 2, UCHAR_MAX + 2); + printf ("printf (\"%%hu\", %u) = %hu\n", USHRT_MAX + 2, USHRT_MAX + 2); +#endif + puts ("--- Should be no further output. ---"); + rfg1 (); + rfg2 (); +#if 0 + rfg3 (); + { + char bytes[7]; + char buf[20]; + + memset (bytes, '\xff', sizeof bytes); + snprintf (buf, sizeof(buf), "foo%hhn\n", &bytes[3]); + if (bytes[0] != '\xff' || bytes[1] != '\xff' || bytes[2] != '\xff' + || bytes[4] != '\xff' || bytes[5] != '\xff' || bytes[6] != '\xff') { + puts ("%hhn overwrite more bytes"); + result = 1; + } + if (bytes[3] != 3) { + puts ("%hhn wrote incorrect value"); + result = 1; + } + } +#endif + return result != 0; +} + +static void rfg1 (void) +{ + char buf[100]; + + snprintf (buf, sizeof(buf), "%5.s", "xyz"); + if (strcmp (buf, " ") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " "); + snprintf (buf, sizeof(buf), "%5.f", 33.3); + if (strcmp (buf, " 33") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 33"); + snprintf (buf, sizeof(buf), "%8.e", 33.3e7); + if (strcmp (buf, " 3e+08") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3e+08"); + snprintf (buf, sizeof(buf), "%8.E", 33.3e7); + if (strcmp (buf, " 3E+08") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3E+08"); + snprintf (buf, sizeof(buf), "%.g", 33.3); + if (strcmp (buf, "3e+01") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3e+01"); + snprintf (buf, sizeof(buf), "%.G", 33.3); + if (strcmp (buf, "3E+01") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3E+01"); +} + +static void rfg2 (void) +{ + int prec; + char buf[100]; + + prec = 0; + snprintf (buf, sizeof(buf), "%.*g", prec, 3.3); + if (strcmp (buf, "3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3"); + prec = 0; + snprintf (buf, sizeof(buf), "%.*G", prec, 3.3); + if (strcmp (buf, "3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3"); + prec = 0; + snprintf (buf, sizeof(buf), "%7.*G", prec, 3.33); + if (strcmp (buf, " 3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3"); + prec = 3; + snprintf (buf, sizeof(buf), "%04.*o", prec, 33); + if (strcmp (buf, " 041") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 041"); + prec = 7; + snprintf (buf, sizeof(buf), "%09.*u", prec, 33); + if (strcmp (buf, " 0000033") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 0000033"); + prec = 3; + snprintf (buf, sizeof(buf), "%04.*x", prec, 33); + if (strcmp (buf, " 021") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 021"); + prec = 3; + snprintf (buf, sizeof(buf), "%04.*X", prec, 33); + if (strcmp (buf, " 021") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 021"); +} + +static void rfg3 (void) +{ + char buf[100]; + double g = 5.0000001; + unsigned long l = 1234567890; + double d = 321.7654321; + const char s[] = "test-string"; + int i = 12345; + int h = 1234; + + snprintf (buf, sizeof(buf), + "%1$*5$d %2$*6$hi %3$*7$lo %4$*8$f %9$*12$e %10$*13$g %11$*14$s", + i, h, l, d, 8, 5, 14, 14, d, g, s, 14, 3, 14); + if (strcmp (buf, + " 12345 1234 11145401322 321.765432 3.217654e+02 5 test-string") != 0) + printf ("got: '%s', expected: '%s'\n", buf, + " 12345 1234 11145401322 321.765432 3.217654e+02 5 test-string"); +} +#endif diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..c6ab0d0 --- /dev/null +++ b/modular.json @@ -0,0 +1,17 @@ +{ + "dep": [ + { + "type": "git", + "provider": "HVAC_M7", + "repo": "BaseTypes" + } + ], + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file