diff options
| author | 2023-05-29 11:37:32 +0200 | |
|---|---|---|
| committer | 2023-05-29 11:37:32 +0200 | |
| commit | 1c04435e5d33378ffa8eca65ca1ed35f3f9f4134 (patch) | |
| tree | eab923f7dde10ba1d71d8efe025891e743009203 /type.c | |
| parent | 84824a0ed3a0cf90728078b74ca39778c51e60b9 (diff) | |
field access
Diffstat (limited to 'type.c')
| -rw-r--r-- | type.c | 40 |
1 files changed, 34 insertions, 6 deletions
@@ -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) { |