Skip to content

Commit 56af209

Browse files
the backtrace file lines should be read at compile time, not runtime
1 parent 6d1b150 commit 56af209

File tree

3 files changed

+51
-45
lines changed

3 files changed

+51
-45
lines changed

src/cognac.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,36 @@ static void* alloc(size_t n)
8282
return (heap += n) - n;
8383
}
8484

85+
char* escape_cstring(char* str)
86+
{
87+
size_t len = strlen(str);
88+
char* str2 = alloc(len*2 + 1);
89+
int ii = 0;
90+
for (int i = 0 ; i < len ; ++i)
91+
{
92+
switch (str[i])
93+
{
94+
case '\\': case '"':
95+
str2[ii++] = '\\';
96+
default:
97+
str2[ii++] = str[i];
98+
break;
99+
}
100+
}
101+
return str2;
102+
}
103+
85104
where_t* parse_pos(char* sym)
86105
{
87106
where_t* p = alloc(sizeof *p);
88107
p->mod = pmod;
89108
p->line = yylloc.first_line;
90109
p->col = yylloc.first_column;
110+
p->line_str = pmod->lines[p->line-1];
91111
p->symbol = sym;
92112
return p;
93113
}
94114

95-
96115
_Noreturn void type_error(val_type_t expected, val_type_t got, where_t* pos)
97116
{
98117
char buf[100];
@@ -410,21 +429,33 @@ module_t* create_module(char* path)
410429

411430
void module_parse(module_t* mod)
412431
{
413-
if (mod->path)
432+
fseek(mod->file, 0, SEEK_SET);
433+
434+
mod->num_lines = 0;
435+
while(!feof(mod->file)) if(fgetc(mod->file) == '\n') mod->num_lines++; // count lines.
436+
437+
mod->lines = alloc(sizeof(char*) * mod->num_lines);
438+
439+
fseek(mod->file, 0, SEEK_SET);
440+
441+
for (int i = 0 ; i < mod->num_lines ; ++i) // populate lines[]
414442
{
415-
FILE* t = fopen(mod->path, "r");
416-
if (!t)
443+
mod->lines[i] = (char*)alloc(1024);
444+
445+
for (int ii = 0 ; ii < 1023 ; ++ii)
417446
{
418-
if (!mod->first_ref)
419-
fprintf(stderr, "\nCan't open file '%s'!\n", mod->path);
420-
else
447+
char c = fgetc(mod->file);
448+
if (c == '\n')
421449
{
422-
throw_error("can't find module", mod->first_ref);
450+
mod->lines[i][ii] = '\0';
451+
break;
423452
}
424-
exit(EXIT_FAILURE);
453+
else mod->lines[i][ii] = c;
425454
}
426-
fclose(t);
455+
mod->lines[i][1023] = '\0';
427456
}
457+
458+
fseek(mod->file, 0, SEEK_SET);
428459
pmod = mod;
429460
yyin = mod->file; // imagine having a reentrant parser.
430461
yylloc.first_line = 1;
@@ -1067,7 +1098,7 @@ void to_c(module_t* mod)
10671098
}
10681099
case backtrace_push:
10691100
if (op->op->where && op->op->where->mod->path && op->op->where->symbol)
1070-
fprintf(c_source, "\tBACKTRACE_PUSH(\"%s\", %zu, %zu, \"%s\", %zu);\n", op->op->where->symbol, op->op->where->line, op->op->where->col, op->op->where->mod->path, bid++);
1101+
fprintf(c_source, "\tBACKTRACE_PUSH(\"%s\", %zu, %zu, \"%s\", \"%s\", %zu);\n", op->op->where->symbol, op->op->where->line, op->op->where->col, escape_cstring(op->op->where->mod->path), escape_cstring(op->op->where->line_str), bid++);
10711102
break;
10721103
case backtrace_pop:
10731104
if (op->op->where && op->op->where->mod->path && op->op->where->symbol)

src/cognac.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ struct _module_t
224224
symbol_list_t* symbols;
225225
module_list_t* uses;
226226
where_t* first_ref;
227+
size_t num_lines;
228+
char** lines;
227229
};
228230

229231
struct _module_list_t
@@ -238,6 +240,7 @@ struct _where_t
238240
size_t line;
239241
size_t col;
240242
char* symbol;
243+
char* line_str;
241244
};
242245

243246
struct _where_list_t

src/runtime.h

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ typedef struct backtrace
131131
const size_t line;
132132
const size_t col;
133133
const char* file;
134+
const char* line_str;
134135
} backtrace;
135136

136137
typedef struct var_info
@@ -384,38 +385,8 @@ static void cleanup(void)
384385

385386
#ifdef DEBUG
386387

387-
static char* get_source_line(size_t line, const char* source_file)
388-
{
389-
// TODO maybe compile the line into the executable instead of rereading the source.
390-
FILE* f = fopen(source_file, "r");
391-
if (!f) return NULL;
392-
393-
for (;;)
394-
{
395-
if (line == 1) break;
396-
if (fgetc(f) == '\n') line--;
397-
}
398-
399-
char* buf = gc_malloc(1024);
400-
401-
int i = 0;
402-
403-
for (;; ++i)
404-
{
405-
char c = fgetc(f);
406-
if (i == 1024 || c == '\n') break;
407-
buf[i] = c;
408-
}
409-
410-
buf[i] = '\0';
411-
412-
fclose(f);
413-
414-
return buf;
415-
}
416-
417-
#define BACKTRACE_PUSH(NAME, LINE, COL, FILE, ID) \
418-
const backtrace _trace_##LINE##_##COL##_##ID = (backtrace) {.name = NAME, .line = (LINE), .col = (COL), .file = (FILE), .next=trace}; \
388+
#define BACKTRACE_PUSH(NAME, LINE, COL, FILE, LINE_STR, ID) \
389+
const backtrace _trace_##LINE##_##COL##_##ID = (backtrace) {.name = NAME, .line = (LINE), .col = (COL), .file = (FILE), .line_str=(LINE_STR), .next=trace}; \
419390
trace = &_trace_##LINE##_##COL##_##ID;
420391

421392
#define BACKTRACE_POP() \
@@ -569,15 +540,16 @@ static void print_backtrace(int n, const backtrace* b, int last_spaces)
569540
{
570541
if (!b || !n) return;
571542
int len = strlen(b->name);
572-
char* ln = get_source_line(b->line, b->file);
573-
if (!ln) fprintf("(can't open source file '%s' to create backtrace)\n", b->file);
543+
const char* ln = b->line_str;
574544
ssize_t col = b->col;
575545
while (*ln)
576546
{
577547
if (*ln != ' ' && *ln != '\t') break;
578548
ln++;
579549
col--;
580550
}
551+
char* tabs;
552+
for (char* tabs ; *tabs ; tabs++) if (*tabs == '\t') *tabs = ' ';
581553
char pos[128];
582554
sprintf(pos, "[%s %zi:%zi]", b->file, b->line, b->col);
583555
int spaces = (strlen(pos)) + col - len/2 - 1;

0 commit comments

Comments
 (0)