--- parse.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- symbol.h | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/parse.c b/parse.c index 02a55a7..cb9bf45 100644 --- a/parse.c +++ b/parse.c @@ -84,7 +84,7 @@ static attr_t attribute_address_space, attribute_context, attribute_designated_init, attribute_transparent_union, ignore_attribute, - attribute_mode, attribute_force; + attribute_mode, attribute_force, attribute_format; typedef struct symbol *to_mode_t(struct symbol *); @@ -353,6 +353,10 @@ static struct symbol_op attr_force_op = { .attribute = attribute_force, }; +static struct symbol_op attr_format = { + .attribute = attribute_format, +}; + static struct symbol_op address_space_op = { .attribute = attribute_address_space, }; @@ -407,6 +411,10 @@ static struct symbol_op mode_word_op = { .to_mode = to_word_mode }; +static struct symbol_op attr_printf_op = { + .type = KW_FORMAT, +}; + /* Using NS_TYPEDEF will also make the keyword a reserved one */ static struct init_keyword { const char *name; @@ -513,6 +521,8 @@ static struct init_keyword { { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, { "address_space",NS_KEYWORD, .op = &address_space_op }, + { "format", NS_KEYWORD, .op = &attr_format }, + { "printf", NS_KEYWORD, .op = &attr_printf_op }, { "mode", NS_KEYWORD, .op = &mode_op }, { "context", NS_KEYWORD, .op = &context_op }, { "designated_init", NS_KEYWORD, .op = &designated_init_op }, @@ -1051,6 +1061,60 @@ static struct token *attribute_address_space(struct token *token, struct symbol return token; } +static struct token *attribute_format(struct token *token, struct symbol *attr, struct decl_state *ctx) +{ + struct expression *args[3]; + struct symbol *fmt_sym = NULL; + int argc = 0; + + printf("token %p, attr %p, context %p\n", token, attr, ctx); + /* expecting format ( type, start, va_args at) */ + + token = expect(token, '(', "after format attribute"); + while (!match_op(token, ')')) { + struct expression *expr = NULL; + + if (argc == 0) { + if (token_type(token) == TOKEN_IDENT) + fmt_sym = lookup_keyword(token->ident, NS_KEYWORD); + + if (!fmt_sym || !fmt_sym->op || + fmt_sym->op != &attr_printf_op) { + sparse_error(token->pos, + "unknown format type '%s'\n", + show_ident(token->ident)); + fmt_sym = NULL; + } + } + + token = conditional_expression(token, &expr); + if (!expr) + break; + if (argc < 3) + args[argc++] = expr; + if (!match_op(token, ',')) + break; + token = token->next; + } + + if (argc != 3 || !fmt_sym) { + sparse_error(token->pos, + "expected format type and start/position values"); + } else { + long long start, at; + + printf("fmt_sym=%p, type %x\n", fmt_sym, fmt_sym->op->type ); + + start = get_expression_value(args[1]); + at = get_expression_value(args[2]); + + printf("fmt: at %lld, start %lld\n", start, at); + } + + token = expect(token, ')', "after format attribute"); + return token; +} + static struct symbol *to_QI_mode(struct symbol *ctype) { if (ctype->ctype.base_type != &int_type) diff --git a/symbol.h b/symbol.h index 3274496..c434196 100644 --- a/symbol.h +++ b/symbol.h @@ -86,6 +86,7 @@ enum keyword { KW_SHORT = 1 << 7, KW_LONG = 1 << 8, KW_EXACT = 1 << 9, + KW_FORMAT = 1 << 10, }; struct context { -- 2.19.1