aboutsummaryrefslogtreecommitdiffhomepage
path: root/lex.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-10-13 19:44:50 +0200
committerlemon <lsof@mailbox.org>2025-10-13 19:46:19 +0200
commit78145f612583750e25090c4d37e418db9aa9c5e2 (patch)
treedd853a7044e7c5040f53d9f5b1e8c6728cc5e5bc /lex.c
parent9812f88a9a612144bea02c7acf499867eb0cbeb9 (diff)
lex: allow ## in non func macros. and error reporting
Diffstat (limited to 'lex.c')
-rw-r--r--lex.c103
1 files changed, 57 insertions, 46 deletions
diff --git a/lex.c b/lex.c
index 20e4c5c..4bc5286 100644
--- a/lex.c
+++ b/lex.c
@@ -719,6 +719,56 @@ ppskipline(struct lexer *lx)
next(lx);
}
+static bool
+tokpaste(struct lexer *lx, struct token *dst, const struct token *l, const struct token *r)
+{
+ char *s;
+ dst->span = l->span;
+ if (dst->span.ex.file == r->span.ex.file && dst->span.ex.off < r->span.ex.off)
+ joinspan(&dst->span.ex, r->span.ex);
+ if (isppident(*l) && (isppident(*r) || r->t == TKNUMLIT)) {
+ /* foo ## bar ; foo ## 123 */
+ dst->t = TKIDENT;
+ } else if (l->t == TKNUMLIT && (isppident(*r) || r->t == TKNUMLIT)) {
+ /* 0x ## abc ; 213 ## 456 */
+ dst->t = TKNUMLIT;
+ } else if (l->t && !r->t) {
+ *dst = *l;
+ return 1;
+ } else if (!l->t && r->t) {
+ *dst = *r;
+ return 1;
+ } else {
+ static const struct { char s[2]; char t; } tab[] = {
+ {"==", TKEQU}, {"!=", TKNEQ}, {"<=", TKLTE}, {">=", TKGTE},
+ {">>", TKSHR}, {"<<", TKSHL}, {"++", TKINC}, {"--", TKDEC},
+ {"->", TKARROW}, {"##", TKPPCAT}, {"&&", TKLOGAND}, {"||", TKLOGIOR},
+ {"+=", TKSETADD}, {"-=", TKSETSUB}, {"*=", TKSETMUL}, {"/=", TKSETDIV},
+ {"%=", TKSETREM}, {"|=", TKSETIOR}, {"^=", TKSETXOR}, {"&=", TKSETAND},
+ {{TKSHL,'='}, TKSETSHL}, {{TKSHR,'='}, TKSETSHR}
+ };
+ struct span span = l->span;
+
+ for (int i = 0; i < arraylength(tab); ++i)
+ if (tab[i].s[0] == l->t && tab[i].s[1] == r->t)
+ return dst->t = tab[i].t, 1;
+
+ joinspan(&span.ex, r->span.ex);
+ error(&span, "pasting %'tk and %'tk does not form a valid preprocessing token", l, r);
+ return 0;
+ }
+
+ /* shared for ident,keyword,numlit */
+ dst->len = l->len + r->len;
+ s = alloc(lx->tmparena, dst->len + 1, 1);
+ memcpy(s, l->s, l->len);
+ memcpy(s + l->len, r->s, r->len);
+ s[l->len + r->len] = 0;
+ if (dst->t == TKIDENT) identkeyword(dst, s, dst->len);
+ else dst->s = s;
+ return 1;
+}
+
static void
ppdefine(struct lexer *lx)
{
@@ -787,6 +837,13 @@ ppdefine(struct lexer *lx)
}
}
}
+ } else if (!mac.fnlike && rlist.n > 1 && rlist.p[rlist.n-1].t == TKPPCAT) {
+ struct token new;
+ if (tokpaste(lx, &new, &rlist.p[rlist.n-2], &tk)) {
+ rlist.p[rlist.n-2] = new;
+ --rlist.n;
+ continue;
+ }
}
vpush(&rlist, tk);
Next:;
@@ -862,52 +919,6 @@ popmac(struct lexer *lx)
}
static bool
-tokpaste(struct lexer *lx, struct token *dst, const struct token *l, const struct token *r)
-{
- char *s;
- dst->span = l->span;
- if (dst->span.ex.file == r->span.ex.file && dst->span.ex.off < r->span.ex.off)
- joinspan(&dst->span.ex, r->span.ex);
- if (isppident(*l) && (isppident(*r) || r->t == TKNUMLIT)) {
- /* foo ## bar ; foo ## 123 */
- dst->t = TKIDENT;
- } else if (l->t == TKNUMLIT && (isppident(*r) || r->t == TKNUMLIT)) {
- /* 0x ## abc ; 213 ## 456 */
- dst->t = TKNUMLIT;
- } else if (l->t && !r->t) {
- *dst = *l;
- return 1;
- } else if (!l->t && r->t) {
- *dst = *r;
- return 1;
- } else {
- static const struct { char s[2]; char t; } tab[] = {
- {"==", TKEQU}, {"!=", TKNEQ}, {"<=", TKLTE}, {">=", TKGTE},
- {">>", TKSHR}, {"<<", TKSHL}, {"++", TKINC}, {"--", TKDEC},
- {"->", TKARROW}, {"##", TKPPCAT}, {"&&", TKLOGAND}, {"||", TKLOGIOR},
- {"+=", TKSETADD}, {"-=", TKSETSUB}, {"*=", TKSETMUL}, {"/=", TKSETDIV},
- {"%=", TKSETREM}, {"|=", TKSETIOR}, {"^=", TKSETXOR}, {"&=", TKSETAND},
- {{TKSHL,'='}, TKSETSHL}, {{TKSHR,'='}, TKSETSHR}
- };
- for (int i = 0; i < arraylength(tab); ++i)
- if (tab[i].s[0] == l->t && tab[i].s[1] == r->t)
- return dst->t = tab[i].t, 1;
- return 0;
- }
-
- /* shared for ident,keyword,numlit */
- dst->len = l->len + r->len;
- s = alloc(lx->tmparena, dst->len + 1, 1);
- memcpy(s, l->s, l->len);
- memcpy(s + l->len, r->s, r->len);
- s[l->len + r->len] = 0;
- if (dst->t == TKIDENT) identkeyword(dst, s, dst->len);
- else dst->s = s;
- return 1;
-}
-
-
-static bool
tryexpand(struct lexer *lx, struct token *tk)
{
static bool inimstk;