feat: render diagnostic source excerpts
This commit is contained in:
@@ -1,9 +1,62 @@
|
|||||||
#include "diag.h"
|
#include "diag.h"
|
||||||
|
|
||||||
|
static unsigned long digits(unsigned long n)
|
||||||
|
{
|
||||||
|
unsigned long count=1;
|
||||||
|
while(n>=10UL){n/=10UL;++count;}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void excerpt(const FeDiags *d, FeLoc loc)
|
||||||
|
{
|
||||||
|
const char *src;
|
||||||
|
unsigned long len;
|
||||||
|
unsigned long i=0;
|
||||||
|
unsigned long line=1;
|
||||||
|
unsigned long start;
|
||||||
|
unsigned long end;
|
||||||
|
unsigned long gutter;
|
||||||
|
unsigned long col;
|
||||||
|
char c;
|
||||||
|
if(!d || !d->source || !d->source_len || !loc.line || !loc.col) return;
|
||||||
|
src=d->source;
|
||||||
|
len=d->source_len;
|
||||||
|
while(i<len && line<loc.line){if(src[i++]=='\n')++line;}
|
||||||
|
if(line!=loc.line || i>len) return;
|
||||||
|
start=i;
|
||||||
|
end=start;
|
||||||
|
while(end<len && src[end]!='\n' && src[end]!='\r')++end;
|
||||||
|
gutter=digits(loc.line);
|
||||||
|
fputs(" ",stderr);
|
||||||
|
fprintf(stderr,"%lu | ",loc.line);
|
||||||
|
if(end>start) fwrite(src+start,1,(size_t)(end-start),stderr);
|
||||||
|
fputc('\n',stderr);
|
||||||
|
fputs(" ",stderr);
|
||||||
|
for(i=0;i<gutter;++i) fputc(' ',stderr);
|
||||||
|
fputs(" | ",stderr);
|
||||||
|
col=1;
|
||||||
|
i=start;
|
||||||
|
while(i<end && col<loc.col){
|
||||||
|
c=src[i++];
|
||||||
|
fputc(c=='\t' ? '\t' : ' ',stderr);
|
||||||
|
++col;
|
||||||
|
}
|
||||||
|
fputs("^\n",stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fe_diags_init(FeDiags *d, const char *source, unsigned long source_len)
|
||||||
|
{
|
||||||
|
d->errors=0;
|
||||||
|
d->warnings=0;
|
||||||
|
d->source=source;
|
||||||
|
d->source_len=source_len;
|
||||||
|
}
|
||||||
|
|
||||||
void fe_diag_error(FeDiags *d, FeLoc loc, const char *msg)
|
void fe_diag_error(FeDiags *d, FeLoc loc, const char *msg)
|
||||||
{
|
{
|
||||||
d->errors++;
|
d->errors++;
|
||||||
fprintf(stderr, "%s:%lu:%lu: error: %s\n", loc.file ? loc.file : "<source>", loc.line, loc.col, msg);
|
fprintf(stderr, "%s:%lu:%lu: error: %s\n", loc.file ? loc.file : "<source>", loc.line, loc.col, msg);
|
||||||
|
excerpt(d,loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_diag_errorf(FeDiags *d, FeLoc loc, const char *msg, const char *arg)
|
void fe_diag_errorf(FeDiags *d, FeLoc loc, const char *msg, const char *arg)
|
||||||
@@ -12,9 +65,16 @@ void fe_diag_errorf(FeDiags *d, FeLoc loc, const char *msg, const char *arg)
|
|||||||
fprintf(stderr, "%s:%lu:%lu: error: ", loc.file ? loc.file : "<source>", loc.line, loc.col);
|
fprintf(stderr, "%s:%lu:%lu: error: ", loc.file ? loc.file : "<source>", loc.line, loc.col);
|
||||||
fprintf(stderr, msg, arg);
|
fprintf(stderr, msg, arg);
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
|
excerpt(d,loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fe_diag_note(FeLoc loc, const char *msg)
|
void fe_diag_note(FeLoc loc, const char *msg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s:%lu:%lu: note: %s\n", loc.file ? loc.file : "<source>", loc.line, loc.col, msg);
|
fprintf(stderr, "%s:%lu:%lu: note: %s\n", loc.file ? loc.file : "<source>", loc.line, loc.col, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fe_diag_note_src(FeDiags *d, FeLoc loc, const char *msg)
|
||||||
|
{
|
||||||
|
fe_diag_note(loc,msg);
|
||||||
|
excerpt(d,loc);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user