ivy-diag is used for generating and emitting diagnostic messages during compilation.
135 lines
2.3 KiB
C
135 lines
2.3 KiB
C
#include "stream.h"
|
|
|
|
#include <blue/term/tty.h>
|
|
#include <string.h>
|
|
|
|
void ivy_diag_stream_init_file(struct ivy_diag_stream *stream, FILE *fp)
|
|
{
|
|
memset(stream, 0x0, sizeof *stream);
|
|
|
|
stream->s_type = IVY_DIAG_STREAM_FILE;
|
|
stream->s_flags = IVY_DIAG_STREAM_F_NONE;
|
|
stream->s_fp = fp;
|
|
stream->s_row = 1;
|
|
stream->s_col = 1;
|
|
}
|
|
|
|
void ivy_diag_stream_init_tty(struct ivy_diag_stream *stream, struct b_tty *tty)
|
|
{
|
|
memset(stream, 0x0, sizeof *stream);
|
|
|
|
stream->s_type = IVY_DIAG_STREAM_TTY;
|
|
stream->s_flags = IVY_DIAG_STREAM_F_COLOUR;
|
|
stream->s_tty = tty;
|
|
stream->s_row = 1;
|
|
stream->s_col = 1;
|
|
}
|
|
|
|
enum ivy_status diag_stream_get_dimensions(
|
|
struct ivy_diag_stream *stream, size_t *out_rows, size_t *out_cols)
|
|
{
|
|
switch (stream->s_type) {
|
|
case IVY_DIAG_STREAM_FILE:
|
|
if (out_rows) {
|
|
*out_rows = (size_t)-1;
|
|
}
|
|
|
|
if (out_cols) {
|
|
*out_cols = (size_t)-1;
|
|
}
|
|
|
|
break;
|
|
case IVY_DIAG_STREAM_TTY: {
|
|
unsigned int w, h;
|
|
b_tty_get_dimensions(stream->s_tty, &w, &h);
|
|
if (out_rows) {
|
|
*out_rows = h;
|
|
}
|
|
|
|
if (out_cols) {
|
|
*out_cols = w;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return IVY_ERR_BAD_STATE;
|
|
}
|
|
|
|
return IVY_OK;
|
|
}
|
|
|
|
enum ivy_status diag_stream_putc(struct ivy_diag_stream *stream, char c)
|
|
{
|
|
enum ivy_status status = IVY_OK;
|
|
|
|
switch (stream->s_type) {
|
|
case IVY_DIAG_STREAM_FILE:
|
|
fputc(c, stream->s_fp);
|
|
|
|
status = (ferror(stream->s_fp)) ? IVY_ERR_IO_FAILURE : IVY_OK;
|
|
break;
|
|
case IVY_DIAG_STREAM_TTY:
|
|
b_tty_putc(stream->s_tty, 0, c);
|
|
status = IVY_OK;
|
|
break;
|
|
default:
|
|
status = IVY_ERR_BAD_STATE;
|
|
break;
|
|
}
|
|
|
|
if (stream->s_esc) {
|
|
if (c == '[' || c == ']') {
|
|
stream->s_esc = 0;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
if (!stream->s_esc && c == '[') {
|
|
stream->s_esc = 1;
|
|
return status;
|
|
}
|
|
|
|
switch (c) {
|
|
case '\r':
|
|
stream->s_col = 1;
|
|
break;
|
|
case '\n':
|
|
stream->s_col = 1;
|
|
stream->s_row++;
|
|
break;
|
|
default:
|
|
stream->s_col++;
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum ivy_status diag_stream_puts(struct ivy_diag_stream *stream, const char *s)
|
|
{
|
|
enum ivy_status status = IVY_OK;
|
|
|
|
while (*s && status == IVY_OK) {
|
|
status = diag_stream_putc(stream, *s);
|
|
s++;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
enum ivy_status diag_stream_printf(
|
|
struct ivy_diag_stream *stream, const char *format, ...)
|
|
{
|
|
enum ivy_status status = IVY_OK;
|
|
va_list arg;
|
|
va_start(arg, format);
|
|
|
|
char buf[256];
|
|
vsnprintf(buf, sizeof buf, format, arg);
|
|
|
|
va_end(arg);
|
|
|
|
return diag_stream_puts(stream, buf);
|
|
}
|