From 731e7a2f3bf18baa4d4ce966006637ee13c5651a Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 24 Oct 2021 22:47:44 -0700 Subject: Add support for C23 attribute syntax Currently, all attributes are ignored. References: https://todo.sr.ht/~mcf/cproc/68 --- attr.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 attr.c (limited to 'attr.c') diff --git a/attr.c b/attr.c new file mode 100644 index 0000000..75ec5ef --- /dev/null +++ b/attr.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include "util.h" +#include "cc.h" + +enum attrprefix { + PREFIXNONE = 1, /* standard attribute */ + PREFIXGNU, +}; + +static char * +strip(char *name) +{ + size_t len; + + len = strlen(name); + if (len >= 4 && name[0] == '_' && name[1] == '_' && name[len - 2] == '_' && name[len - 1] == '_') { + name[len - 2] = '\0'; + name += 2; + } + return name; +} + +static bool +parseattr(struct attr *a, enum attrkind allowed, enum attrprefix prefix) +{ + char *name, *prefixname = ""; + enum attrkind kind; + int paren; + + if (tok.kind != TIDENT) + return false; + name = strip(tok.lit); + next(); + if (!prefix) { + if (consume(TCOLONCOLON)) { + if (strcmp(name, "gnu") == 0) + prefix = PREFIXGNU; + else + prefix = 0; + name = strip(expect(TIDENT, "after attribute prefix")); + } else { + prefix = PREFIXNONE; + } + } + kind = 0; + switch (prefix) { + case PREFIXGNU: + prefixname = "GNU "; + break; + } + if (kind) { + if (!(kind & allowed)) + error(&tok.loc, "%sattribute '%s' is not supported here", prefixname, name); + if (a) + a->kind |= kind; + } else if (consume(TLPAREN)) { + /* skip arguments */ + for (paren = 1; paren > 0; next()) { + switch (tok.kind) { + case TLPAREN: ++paren; break; + case TRPAREN: --paren; break; + } + } + } + return true; +} + +static bool +attrspec(struct attr *a, enum attrkind allowed) +{ + if (tok.kind != TLBRACK || !peek(TLBRACK)) + return false; + while (parseattr(a, allowed, 0) || consume(TCOMMA)) + ; + expect(TRBRACK, "to end attribute specifier"); + expect(TRBRACK, "to end attribute specifier"); + return true; +} + +bool +attr(struct attr *a, enum attrkind allowed) +{ + if (!attrspec(a, allowed)) + return false; + while (attrspec(a, allowed)) + ; + return true; +} -- cgit v1.2.3