From 1c04435e5d33378ffa8eca65ca1ed35f3f9f4134 Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 29 May 2023 11:37:32 +0200 Subject: field access --- type.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'type.c') diff --git a/type.c b/type.c index 5f984d6..66e5e63 100644 --- a/type.c +++ b/type.c @@ -98,15 +98,12 @@ interntd(const struct typedata *td) case TYUNION: if (slot->fld) slot->fld = alloccopy(&datarena, td->fld, nmemb * sizeof *slot->fld, 0); - Qual: - if (slot->quals) - slot->quals = alloccopy(&datarena, td->quals, tdqualsiz(nmemb), 1); break; case TYFUNC: - if (slot->param) { + if (slot->param) slot->param = alloccopy(&datarena, td->param, nmemb * sizeof *slot->param, 0); - } - goto Qual; + if (slot->quals) + slot->quals = alloccopy(&datarena, td->quals, tdqualsiz(nmemb), 1); } return i; } else if (tdequ(slot, td)) { @@ -214,6 +211,37 @@ mktagtype(const char *name, struct typedata *td) return completetype(name, id++, td); } +static bool +getfieldrec(struct fielddata *res, uint off, const struct typedata *td, const char *name) +{ +Begin: + for (int i = 0; i < td->nmemb; ++i) { + struct namedfield *fld = &td->fld[i]; + if (fld->name == name) { /* match */ + *res = fld->f; + res->off += off; + return 1; + } else if (!fld->name) { /* anonymous struct/union */ + const struct typedata *ftd = &typedata[fld->f.t.dat]; + assert(isagg(fld->f.t)); + if (i == td->nmemb - 1) { /* last field, tail recurse */ + off += fld->f.off; + td = ftd; + goto Begin; + } else if (getfieldrec(res, off + fld->f.off, ftd, name)) + return 1; + } + } + return 0; +} + +bool +getfield(struct fielddata *res, union type ty, const char *name) +{ + assert(isagg(ty)); + return getfieldrec(res, 0, &typedata[ty.dat], name); +} + union type typedecay(union type t) { -- cgit v1.2.3