/* * stc_msg_vformat * * The core formatting routine. * Do NOT use sprintf-style formatting codes in * message strings! Use the formatting directives * below: * !SL = text with length (char *str, int len) * !SZ = null-terminated string (char *azstr) * !SD = string descriptor (strdesc_t *sdsc) * !U{I,S,L} = unsigned int, short, long * !I{I,S,L} = signed int, short, long * !X{I,S,L} = hexadecimal int, short, long * !P = pointer * !! = exclamation point */ int stc_msg_vformat (statcode_t statcode, char *buf, size_t bufsiz, va_list ap) { int len; char tmpbuf[32]; char *outp; const char *fmt; unsigned int msgno = stc_msgno(statcode); unsigned int sev = stc_severity(statcode); if (msgno >= MSG_COUNT) { return snprintf(buf, bufsiz, "%%BLISS-%c-UNKNOWN: unknown message code %u", sevchars[sev], msgno); } len = snprintf(buf, bufsiz, "%%BLISS-%c-%s, ", sevchars[sev], mcnames[msgno]); if (len >= bufsiz) len = (int) bufsiz - 1; outp = buf + len; bufsiz -= len; fmt = mctext[msgno]; while (bufsiz > 0 && *fmt != '\0') { if (*fmt != '!') { *outp++ = *fmt++; bufsiz -= 1; continue; } fmt += 1; if (*fmt == '\0') break; if (*fmt == '!') { *outp++ = *fmt++; bufsiz -= 1; continue; } if (*fmt == 'U' || *fmt == 'X') { unsigned long val; if (*(fmt+1) == 'L') { val = va_arg(ap, unsigned long); } else if (*(fmt+1) == 'S' || *(fmt+1) == 'I') {
/* * log_vsignal * * Core logging function. Formats the diagnostic message and text * position (if possible), emits the message on stderr, and handles * the next step - incrementing the appropriate diagnostic counter * and possibly aborting. */ void log_vsignal (logctx_t ctx, textpos_t pos, statcode_t code, va_list ap) { char logbuf[256]; int len; unsigned int sev = stc_severity(code); if (sev == STC_K_FATAL) { ctx->logtoterm = 1; } if (ctx->listprintfn != 0 || ctx->logtoterm) { int fileno = textpos_fileno(pos); unsigned int lineno = textpos_lineno(pos); unsigned int colno = textpos_colnum(pos); if (ctx->linefetchfn != 0) { strdesc_t *curline = (*ctx->linefetchfn)(ctx->lfctx, fileno, lineno); if (curline != 0) { doprintsrc(ctx, curline->ptr, curline->len); if (curline->len < sizeof(logbuf) && colno < curline->len) { memset(logbuf, '.', colno); logbuf[colno] = '|'; doprint(ctx, logbuf, colno+1, !ctx->logsrctolst); } } } len = stc_msg_vformat(code, logbuf, sizeof(logbuf)-1, ap); doprint(ctx, logbuf, len, 0); if (pos != 0 && ctx->fetchfn != 0) { strdesc_t *fname = ctx->fetchfn(ctx->ffctx, fileno); if (fname != 0) { len = snprintf(logbuf, sizeof(logbuf)-1, "- at %-*.*s:%u:%u", fname->len, fname->len, fname->ptr, lineno, colno+1); if (len > 0) doprint(ctx, logbuf, len, 0); } } } switch (sev) { case STC_K_ERROR: ctx->errcount += 1; if (ctx->errcount < ctx->maxerrs) break; // Force this error message to the terminal ctx->logtoterm = 1; len = snprintf(logbuf, sizeof(logbuf)-1, "%%BLISS-F-TOOMANYERRS, " "maximum number of errors exceeded, aborting"); if (len > 0) doprint(ctx, logbuf, len, 0); // FALLTHROUGH case STC_K_FATAL: fflush(stderr); longjmp(ctx->retenv, 1); break; case STC_K_WARN: ctx->warncount += 1; break; case STC_K_INFO: ctx->infocount += 1; break; default: break; } } /* log_vsignal */