#include #include #include #include "type.h" #define builtin_scalar(_t) { \ .ttype = T_SCALAR, \ .size = sizeof(_t), \ .t = { .scalar = { .name = #_t } }, \ } #define builtin_pointer(_t) { \ .ttype = T_POINTER, \ .t = { .pointer = { .type = _t } }, \ } type_t t_v = builtin_scalar(void); type_t t_vp = builtin_pointer(&t_v); type_t t_c = builtin_scalar(char); type_t t_cp = builtin_pointer(&t_c); type_t t_uc = builtin_scalar(unsigned char); type_t t_ucp = builtin_pointer(&t_uc); type_t t_s = builtin_scalar(short); type_t t_sp = builtin_pointer(&t_s); type_t t_us = builtin_scalar(unsigned short); type_t t_usp = builtin_pointer(&t_us); type_t t_i = builtin_scalar(int); type_t t_ip = builtin_pointer(&t_i); type_t t_ui = builtin_scalar(unsigned int); type_t t_uip = builtin_pointer(&t_ui); type_t t_l = builtin_scalar(long); type_t t_lp = builtin_pointer(&t_l); type_t t_ul = builtin_scalar(unsigned long); type_t t_ulp = builtin_pointer(&t_ul); type_t t_ll = builtin_scalar(long long); type_t t_llp = builtin_pointer(&t_ll); type_t t_ull = builtin_scalar(unsigned long long); type_t t_ullp = builtin_pointer(&t_ull); type_t *builtin_types[] = { &t_v, &t_vp, &t_c, &t_cp, &t_uc, &t_ucp, &t_s, &t_sp, &t_us, &t_usp, &t_i, &t_ip, &t_ui, &t_uip, &t_l, &t_lp, &t_ul, &t_ulp, &t_ll, &t_llp, &t_ull, &t_ullp, NULL }; struct type_list { type_t **type; size_t len; } types; void type_dump_func(type_t *t, FILE *fp) { field_t *arg; type_dump(t->t.func.type, fp); fprintf(fp, " (*%s)(", t->t.func.name ? : ""); if (!t->t.func.args) { fputs("void)", fp); return; } for (arg = t->t.func.args; arg->type; arg++) { if (arg != t->t.func.args) fputs(", ", fp); type_dump(arg->type, fp); } fputc(')', fp); } void type_dump(type_t *t, FILE *fp) { if (!t) { fputs("", fp); return; } switch (t->ttype){ case T_TYPEDEF: fputs(t->t.tdef.name, fp); break; case T_SCALAR: fputs(t->t.scalar.name, fp); break; case T_POINTER: type_dump(t->t.pointer.type, fp); fputs(" *", fp); break; case T_ARRAY: type_dump(t->t.array.type, fp); fprintf(fp, "[%zu]", t->t.array.len); break; case T_STRUCT: fputs("struct ", fp); fputs(t->t.sou.name, fp); break; case T_UNION: fputs("union ", fp); fputs(t->t.sou.name, fp); break; case T_FUNC: type_dump_func(t, fp); break; case T_MAP: /* TODO */ assert(0); break; } } void type_dump_cdecl_sou(type_t *t, FILE *fp) { field_t *f; type_dump(t, fp); fputs(" {\n", fp); for (f = t->t.sou.fields; f->type; f++) { fputc('\t', fp); type_dump(f->type, fp); fprintf(fp, " %s;\n", f->name); } fputs("}", fp); } void type_dump_cdecl(type_t *t, FILE *fp) { switch (t->ttype) { case T_TYPEDEF: fputs("typedef ", fp); type_dump(t->t.tdef.type, fp); fprintf(fp, " %s", t->t.tdef.name); break; case T_STRUCT: case T_UNION: type_dump_cdecl_sou(t, fp); break; case T_SCALAR: case T_POINTER: case T_ARRAY: case T_MAP: case T_FUNC: type_dump(t, fp); break; } } void types_dump_cdecl(FILE *fp) { size_t i; for (i = 0; i < types.len; i++) { type_t *t = types.type[i]; type_dump_cdecl(t, stdout); printf(" \n", t->size); } } int type_equal(type_t *a, type_t *b) { /* TODO */ return a == b; } void type_size_set_sou(type_t *t) { field_t *f; size_t size = 0; if (!t->t.sou.fields) return; for (f = t->t.sou.fields; f->name; f++) { /* size of all members is now known yet, abort */ if (!f->type->size) return; if (!t->t.sou.packed) size += size % f->type->size; size += f->type->size; f->offset = size; } if (!t->t.sou.packed && size) { /* align complete struct to requirements of first * member */ f = t->t.sou.fields; size += size % f->type->size; } t->size = size; } void type_size_set(type_t *t) { switch (t->ttype) { case T_TYPEDEF: t->size = t->t.tdef.type->size; break; case T_STRUCT: case T_UNION: type_size_set_sou(t); break; case T_FUNC: t->size = t->t.func.type->size; break; case T_SCALAR: break; case T_POINTER: t->size = sizeof(void *); break; case T_ARRAY: t->size = t->t.array.len * t->t.array.type->size; break; case T_MAP: /* TODO */ assert(0); break; } } int type_cmp(const void *_a, const void *_b) { const type_t *a = *((type_t **)_a); const type_t *b = *((type_t **)_b); return a - b; } int type_add(type_t *t) { if (bsearch(t, types.type, types.len, sizeof(*types.type), type_cmp)) return 0; type_size_set(t); types.type = realloc(types.type, ++types.len * sizeof(*types.type)); types.type[types.len - 1] = t; qsort(types.type, types.len, sizeof(*types.type), type_cmp); return 0; } int type_add_list(type_t **ts) { int err; for (; *ts; ts++) { err = type_add(*ts); if (err) return err; } return 0; } __attribute__((constructor)) static void type_init(void) { type_add_list(builtin_types); }