I agree the feature can be useful. We might add it in a future release.
We are also thinking about adding an optional C like preprocessor in
QuickJS (with at least #if/#endif and #define for simple identifiers).
Best regards,
Fabrice.
On 9/4/19 1:45 PM, Mario Gliewe wrote:
Hi,
while playing along with qjsc, i found it convinient to use the regular
c preprocessor when precompiling javascript to bytecode.
The problem was, that cpp would put out '#line' statements (actually: '#
nn "fname"') .
Here's a patch to make quickjs aware of these.. it will give usefull
filename/lino info in stacktraces.
caveats:
- it will leak some amount of memory for each '#line' sourceline, since
filename strings are never free()'d; i guess to avoid that, the
JSParseState's filename would have to be transformed into a JS_SYMBOL
- when having an #include inside a function, stacktraces will give wrong
filenames
greets
maG
--snip--
mag@mag-laptop:~/code/quickjs-2019-08-10$ git diff quickjs.c
diff --git a/quickjs.c b/quickjs.c
index 7bb20cb..6e14b37 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -19152,16 +19152,56 @@ static __exception int
js_parse_regexp(JSParseState *s)
static __exception int next_token(JSParseState *s)
{
const uint8_t *p;
- int c;
+ int c, lino;
char buf[4096], *q;
BOOL ident_has_escape;
free_token(s, &s->token);
p = s->last_ptr = s->buf_ptr;
- s->got_lf = FALSE;
+
+
+ if (s->line_num>0) // line_num==0 indicates start of parse stream
+ s->got_lf = FALSE;
+ else
+ s->line_num = 1;
+
s->last_line_num = s->token.line_num;
redo:
+ if (*p && s->got_lf) {
+ // parse cpp #line statements: '# nnn "fname"
+ // this might interfere with some valid ecma statements
(private names starting on new line),
+ // so we handle lines starting with whitspace as normal
javascript, and only consider '#' followed by whitespace
+ if (*p == '#' && (p[1]!=' ' && p[1] != '\t')) {
+ p++;
+ while (*p == '\t' || *p==' ')
+ p++;
+ if (*p>='0' && *p<='9') {
+ lino=0;
+ while (*p>='0' && *p<='9')
+ lino = lino*10 + (*p++)-'0';
+ s->line_num = lino;
+ while (*p == '\t' || *p==' ')
+ p++;
+ if (*p == '"') {
+ p++;
+ q=buf;
+ while (*p && *p!='"' && *p!='\r' && *p != '\n') {
+ if (q-buf < 4095)
+ *q++=*p++;
+ }
+ *q=0;
+ s->filename = js_strdup(s->ctx, buf);
+ }
+ while (* p && *p != '\r' && *p!='\n')
+ p++;
+ if (*p == '\r') p++;
+ if (*p == '\n') p++;
+ }
+ goto redo;
+ }
+ }
+
s->token.line_num = s->line_num;
s->token.ptr = p;
c = *p;
@@ -31084,9 +31124,10 @@ static void js_parse_init(JSContext *ctx,
JSParseState *s,
const char *filename)
{
memset(s, 0, sizeof(*s));
+ s->got_lf = TRUE;
s->ctx = ctx;
s->filename = filename;
- s->line_num = 1;
+ s->line_num = 0;
s->buf_ptr = (const uint8_t *)input;
s->buf_end = s->buf_ptr + input_len;
s->token.val = ' ';