static attribute *parse_attr_cleanup(symtable *scope, const char *ident) { char *sp; where ident_loc; attribute *attr = NULL; struct symtab_entry ent; (void)ident; EAT(token_open_paren); if(curtok != token_identifier) die_at(NULL, "identifier expected for cleanup function"); where_cc1_current(&ident_loc); sp = token_current_spel(); EAT(token_identifier); if(symtab_search(scope, sp, NULL, &ent) && ent.type == SYMTAB_ENT_DECL) { attr = attribute_new(attr_cleanup); attr->bits.cleanup = ent.bits.decl; } else { warn_at_print_error(&ident_loc, "function '%s' not found", sp); fold_had_error = 1; } EAT(token_close_paren); return attr; }
static attribute *parse_attr_format(symtable *symtab, const char *ident) { /* __attribute__((format (printf, fmtarg, firstvararg))) */ attribute *da; char *func; enum fmt_type fmt; (void)symtab; (void)ident; EAT(token_open_paren); func = token_current_spel(); EAT(token_identifier); /* TODO: token_current_spel() * and token_get_current_str(..,..) * checks everywhere */ if(!func) return NULL; #define CHECK(s) !strcmp(func, s) || !strcmp(func, "__" s "__") if(CHECK("printf")) { fmt = attr_fmt_printf; } else if(CHECK("scanf")) { fmt = attr_fmt_scanf; } else { cc1_warn_at(NULL, attr_format_unknown, "unknown format func \"%s\"", func); parse_attr_bracket_chomp(1); return NULL; } da = attribute_new(attr_format); da->bits.format.fmt_func = fmt; EAT(token_comma); da->bits.format.fmt_idx = currentval.val.i - 1; EAT(token_integer); EAT(token_comma); da->bits.format.var_idx = currentval.val.i - 1; EAT(token_integer); EAT(token_close_paren); return da; }
char *curtok_to_identifier(int *alloc) { switch(curtok){ case token_do: case token_if: case token_else: case token_while: case token_for: case token_break: case token_return: case token_switch: case token_case: case token_default: case token_continue: case token_goto: case token_asm: case token_sizeof: case token_typeof: case token__Generic: case token__Static_assert: case token_extern: case token_static: case token_auto: case token_register: case token__Alignof: case token__Alignas: case token_inline: case token__Noreturn: case token_const: case token_volatile: case token_restrict: case token_void: case token_char: case token_short: case token_int: case token_long: case token_float: case token_double: case token__Bool: case token_signed: case token_unsigned: case token_typedef: case token_struct: case token_union: case token_enum: case token___builtin_va_list: case token_attribute: case token___extension__: case token___auto_type: case token___label__: /* we can stringify these */ *alloc = 0; return token_to_str(curtok); case token_identifier: *alloc = 1; return token_current_spel(); case token_integer: case token_floater: case token_character: case token_string: case token_elipsis: case token_open_paren: case token_open_block: case token_open_square: case token_close_paren: case token_close_block: case token_close_square: case token_comma: case token_semicolon: case token_colon: case token_plus: case token_minus: case token_multiply: case token_divide: case token_modulus: case token_increment: case token_decrement: case token_assign: case token_dot: case token_eq: case token_le: case token_lt: case token_ge: case token_gt: case token_ne: case token_not: case token_bnot: case token_andsc: case token_and: case token_orsc: case token_or: case token_xor: case token_question: case token_plus_assign: case token_minus_assign: case token_multiply_assign: case token_divide_assign: case token_modulus_assign: case token_not_assign: case token_bnot_assign: case token_and_assign: case token_or_assign: case token_xor_assign: case token_shiftl: case token_shiftr: case token_shiftl_assign: case token_shiftr_assign: case token_ptr: case token_eof: case token_unknown: break; } return NULL; }