* for reporting of file:line based on lexer context, These are used
* heavily in the parser/ir/ast.
*/
-static void con_vprintmsg_c(int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap, const char *condname) {
+static void con_vprintmsg_c(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap, const char *condname) {
/* color selection table */
static int sel[] = {
CON_WHITE,
int (*vprint)(const char *, va_list) = (err) ? &con_verr : &con_vout;
if (color)
- print("\033[0;%dm%s:%d: \033[0;%dm%s: \033[0m", CON_CYAN, name, (int)line, sel[level], msgtype);
+ print("\033[0;%dm%s:%d:%d: \033[0;%dm%s: \033[0m", CON_CYAN, name, (int)line, (int)column, sel[level], msgtype);
else
- print("%s:%d: %s: ", name, (int)line, msgtype);
+ print("%s:%d:%d: %s: ", name, (int)line, (int)column, msgtype);
vprint(msg, ap);
if (condname)
print("\n");
}
-void con_vprintmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap) {
- con_vprintmsg_c(level, name, line, msgtype, msg, ap, NULL);
+void con_vprintmsg(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap) {
+ con_vprintmsg_c(level, name, line, column, msgtype, msg, ap, NULL);
}
-void con_printmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, ...) {
+void con_printmsg(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, ...) {
va_list va;
va_start(va, msg);
- con_vprintmsg(level, name, line, msgtype, msg, va);
+ con_vprintmsg(level, name, line, column, msgtype, msg, va);
va_end (va);
}
void con_cvprintmsg(void *ctx, int lvl, const char *msgtype, const char *msg, va_list ap) {
- con_vprintmsg(lvl, ((lex_ctx*)ctx)->file, ((lex_ctx*)ctx)->line, msgtype, msg, ap);
+ con_vprintmsg(lvl, ((lex_ctx*)ctx)->file, ((lex_ctx*)ctx)->line, ((lex_ctx*)ctx)->column, msgtype, msg, ap);
}
void con_cprintmsg (void *ctx, int lvl, const char *msgtype, const char *msg, ...) {
lvl = LVL_ERROR;
}
- con_vprintmsg_c(lvl, ctx.file, ctx.line, msgtype, fmt, ap, warn_name);
+ con_vprintmsg_c(lvl, ctx.file, ctx.line, ctx.column, msgtype, fmt, ap, warn_name);
return OPTS_WERROR(warntype) && OPTS_FLAG(BAIL_ON_WERROR);
}
void ftepp_add_define(ftepp_t *ftepp, const char *source, const char *name)
{
ppmacro *macro;
- lex_ctx ctx = { "__builtin__", 0 };
+ lex_ctx ctx = { "__builtin__", 0, 0 };
ctx.file = source;
macro = ppmacro_new(ctx, name);
/*vec_push(ftepp->macros, macro);*/
typedef struct {
const char *file;
size_t line;
+ size_t column;
} lex_ctx;
/*===================================================================*/
FILE *con_default_out();
FILE *con_default_err();
-void con_vprintmsg (int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap);
-void con_printmsg (int level, const char *name, size_t line, const char *msgtype, const char *msg, ...);
+void con_vprintmsg (int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap);
+void con_printmsg (int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, ...);
void con_cvprintmsg(void *ctx, int lvl, const char *msgtype, const char *msg, va_list ap);
void con_cprintmsg (void *ctx, int lvl, const char *msgtype, const char *msg, ...);
va_start(ap, fmt);
if (lex)
- con_vprintmsg(LVL_ERROR, lex->name, lex->sline, "parse error", fmt, ap);
+ con_vprintmsg(LVL_ERROR, lex->name, lex->sline, lex->column, "parse error", fmt, ap);
else
- con_vprintmsg(LVL_ERROR, "", 0, "parse error", fmt, ap);
+ con_vprintmsg(LVL_ERROR, "", 0, 0, "parse error", fmt, ap);
va_end(ap);
}
#else
if (lex->tok.value)
vec_shrinkto(lex->tok.value, 0);
+
lex->tok.constval.t = 0;
- lex->tok.ctx.line = lex->sline;
- lex->tok.ctx.file = lex->name;
+ lex->tok.ctx.line = lex->sline;
+ lex->tok.ctx.file = lex->name;
+ lex->tok.ctx.column = lex->column;
#endif
}
#endif
memset(lex, 0, sizeof(*lex));
- lex->file = in;
- lex->name = util_strdup(file);
- lex->line = 1; /* we start counting at 1 */
-
+ lex->file = in;
+ lex->name = util_strdup(file);
+ lex->line = 1; /* we start counting at 1 */
+ lex->column = 0;
lex->peekpos = 0;
- lex->eof = false;
+ lex->eof = false;
vec_push(lex_filenames, lex->name);
return lex;
lex->open_string_length = len;
lex->open_string_pos = 0;
- lex->name = util_strdup(name ? name : "<string-source>");
- lex->line = 1; /* we start counting at 1 */
-
+ lex->name = util_strdup(name ? name : "<string-source>");
+ lex->line = 1; /* we start counting at 1 */
lex->peekpos = 0;
- lex->eof = false;
+ lex->eof = false;
+ lex->column = 0;
vec_push(lex_filenames, lex->name);
static int lex_fgetc(lex_file *lex)
{
- if (lex->file)
+ if (lex->file) {
+ lex->column++;
return fs_file_getc(lex->file);
+ }
if (lex->open_string) {
if (lex->open_string_pos >= lex->open_string_length)
return EOF;
+ lex->column++;
return lex->open_string[lex->open_string_pos++];
}
return EOF;
{
int c2, c3;
c2 = lex_fgetc(lex);
- if (!lex->push_line && c2 == '\n')
+ if (!lex->push_line && c2 == '\n') {
lex->line++;
+ lex->column = 0;
+ }
+
if (c2 != '?') {
lex_ungetch(lex, c2);
return old;
}
c3 = lex_fgetc(lex);
- if (!lex->push_line && c3 == '\n')
+ if (!lex->push_line && c3 == '\n') {
lex->line++;
+ lex->column = 0;
+ }
+
switch (c3) {
case '=': return '#';
case '/': return '\\';
static void lex_ungetch(lex_file *lex, int ch)
{
lex->peek[lex->peekpos++] = ch;
- if (!lex->push_line && ch == '\n')
+ lex->column--;
+ if (!lex->push_line && ch == '\n') {
lex->line--;
+ lex->column = 0;
+ }
}
/* classify characters
ch = 0;
else {
--u8len;
+ lex->column += u8len;
for (uc = 0; uc < u8len; ++uc)
lex_tokench(lex, u8buf[uc]);
/* the last character will be inserted with the tokench() call
char *name;
size_t line;
size_t sline; /* line at the start of a token */
+ size_t column;
int peek[256];
size_t peekpos;
if ((line = opts_ini_parse(ini, &opts_ini_load, &error)) != 0) {
/* there was a parse error with the ini file */
- con_printmsg(LVL_ERROR, file, line, "error", error);
+ con_printmsg(LVL_ERROR, file, line, 0 /*TODO: column for ini error*/, "error", error);
vec_free(error);
}
case 'I': destval = &tmpl->sourcefile; break;
case 'F': destval = &tmpl->testflags; break;
default:
- con_printmsg(LVL_ERROR, __FILE__, __LINE__, "internal error",
+ con_printmsg(LVL_ERROR, __FILE__, __LINE__, 0, "internal error",
"invalid tag `%c:` during code generation\n",
tag
);
* assigned value.
*/
if (*destval) {
- con_printmsg(LVL_ERROR, file, line, "compile error",
+ con_printmsg(LVL_ERROR, file, line, 0, /*TODO: column for match*/ "compile error",
"tag `%c:` already assigned value: %s\n",
tag, *destval
);
*/
case '/':
if (data[1] != '/') {
- con_printmsg(LVL_ERROR, file, line, "tmpl parse error",
+ con_printmsg(LVL_ERROR, file, line, 0, /*TODO: column for match*/ "tmpl parse error",
"invalid character `/`, perhaps you meant `//` ?");
mem_d(back);
case 'I':
case 'F':
if (data[1] != ':') {
- con_printmsg(LVL_ERROR, file, line, "tmpl parse error",
+ con_printmsg(LVL_ERROR, file, line, 0, /*TODO: column for match*/ "tmpl parse error",
"expected `:` after `%c`",
*data
);
goto failure;
}
if (!task_template_generate(tmpl, *data, file, line, &data[3], pad)) {
- con_printmsg(LVL_ERROR, file, line, "tmpl compile error",
+ con_printmsg(LVL_ERROR, file, line, 0, /*TODO: column for match*/ "tmpl compile error",
"failed to generate for given task\n"
);
goto failure;
{
char *value = &data[3];
if (data[1] != ':') {
- con_printmsg(LVL_ERROR, file, line, "tmpl parse error",
+ con_printmsg(LVL_ERROR, file, line, 0, /*TODO: column for match*/ "tmpl parse error",
"expected `:` after `%c`",
*data
);
}
default:
- con_printmsg(LVL_ERROR, file, line, "tmpl parse error",
+ con_printmsg(LVL_ERROR, file, line, 0, /*TODO: column for match*/ "tmpl parse error",
"invalid tag `%c`", *data
);
goto failure;