@@ -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)
@@ -86,6 +86,7 @@ enum keyword {
KW_SHORT = 1 << 7,
KW_LONG = 1 << 8,
KW_EXACT = 1 << 9,
+ KW_FORMAT = 1 << 10,
};
struct context {