return ret;
}
+static size_t advance(char **buf, size_t *n, size_t amount)
+{
+ if (!amount)
+ return 0;
+
+ if (amount >= *n) {
+ *n = 0;
+ *buf = 0;
+ } else {
+ (*buf)[amount] = ' ';
+ if (amount + 1 >= *n) {
+ *buf = 0;
+ *n = 0;
+ } else {
+ *buf += amount + 1;
+ *n -= amount + 1;
+ }
+ }
+
+ return amount + 1;
+}
+
+static size_t
+explain_qualifiers(char *buf, size_t n, struct cdecl_declspec *s)
+{
+ unsigned long qualmap = 0;
+ size_t ret = 0, rc = 0;
+
+ for (struct cdecl_declspec *c = s; c; c = c->next) {
+ if (cdecl_spec_kind(c) != CDECL_SPEC_QUAL)
+ continue;
+ qualmap |= 1ul << (c->type & 0xff);
+ }
+
+ if (qualmap & (1ul << (CDECL_QUAL_RESTRICT & 0xff))) {
+ ret += advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "restrict");
+ }
+ if (qualmap & (1ul << (CDECL_QUAL_VOLATILE & 0xff))) {
+ ret += advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "volatile");
+ }
+ if (qualmap & (1ul << (CDECL_QUAL_CONST & 0xff))) {
+ ret += advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "const");
+ }
+
+ return ret + rc;
+}
+
/* Renders the type qualifiers and type specifiers in canonical form. */
static size_t
explain_post_specs(char *buf, size_t n, struct cdecl_declspec *s)
{
- unsigned long qualmap = 0, typemap;
const char *tag = NULL;
- size_t ret = 0;
+ unsigned long typemap;
+ size_t ret = 0, rc;
typemap = cdecl__build_typemap(s);
if (typemap == -1)
return 0;
for (struct cdecl_declspec *c = s; c; c = c->next) {
- switch (cdecl_spec_kind(c)) {
- case CDECL_SPEC_QUAL:
- qualmap |= 1ul << (c->type & 0xff);
- break;
- case CDECL_SPEC_TYPE:
- /* Valid C types have at most one identifier. */
- if (c->ident)
- tag = c->ident;
- break;
- }
+ if (cdecl_spec_kind(c) != CDECL_SPEC_TYPE)
+ continue;
+
+ /* Valid C types have at most one identifier. */
+ if (c->ident)
+ tag = c->ident;
}
- if (qualmap & (1ul << (CDECL_QUAL_RESTRICT & 0xff)))
- ret += output(buf, n, ret, "restrict ");
- if (qualmap & (1ul << (CDECL_QUAL_VOLATILE & 0xff)))
- ret += output(buf, n, ret, "volatile ");
- if (qualmap & (1ul << (CDECL_QUAL_CONST & 0xff)))
- ret += output(buf, n, ret, "const ");
+ rc = explain_qualifiers(buf, n, s);
+ ret += advance(&buf, &n, rc);
- ret += output(buf, n, ret, "%s", cdecl__explain_typemap(typemap));
- if (tag)
- ret += output(buf, n, ret, " %s", tag);
- return ret;
+ rc = snprintf(buf, n, "%s", cdecl__explain_typemap(typemap));
+ if (tag) {
+ ret += advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "%s", tag);
+ }
+
+ return ret + rc;
}
static const char *explain_storage(unsigned spec)
return ret;
}
-static size_t advance(char **buf, size_t *n, size_t amount)
-{
- if (!amount)
- return 0;
-
- if (amount >= *n) {
- *n = 0;
- *buf = 0;
- } else {
- (*buf)[amount] = ' ';
- if (amount + 1 >= *n) {
- *buf = 0;
- *n = 0;
- } else {
- *buf += amount + 1;
- *n -= amount + 1;
- }
- }
-
- return amount + 1;
-}
size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl)
{