#include <stdio.h>
+#include <assert.h>
+
+#include "typemap.h"
#include "output.h"
+#include "cdecl.h"
size_t cdecl__advance_(char **buf, size_t *n, size_t amount)
{
rc = snprintf(*buf, *n, " ");
return ret + cdecl__advance_(buf, n, rc);
}
+
+static size_t explain_storage(char *buf, size_t n, unsigned spec)
+{
+ switch (spec) {
+ case CDECL_STOR_TYPEDEF:
+ return snprintf(buf, n, "typedef");
+ case CDECL_STOR_EXTERN:
+ return snprintf(buf, n, "extern");
+ case CDECL_STOR_STATIC:
+ return snprintf(buf, n, "static");
+ case CDECL_STOR_AUTO:
+ return snprintf(buf, n, "auto");
+ case CDECL_STOR_REGISTER:
+ return snprintf(buf, n, "register");
+ default:
+ assert(0);
+ }
+}
+
+/* Renders the storage-class and function specifiers in canonical form. */
+size_t cdecl__explain_pre_specs(char *buf, size_t n, struct cdecl_declspec *s)
+{
+ unsigned long funcmap = 0;
+ size_t ret = 0, rc = 0;
+
+ for (struct cdecl_declspec *c = s; c; c = c->next) {
+ switch (cdecl_spec_kind(c)) {
+ case CDECL_SPEC_FUNC:
+ funcmap |= 1ul << (c->type & 0xff);
+ break;
+ case CDECL_SPEC_STOR:
+ /* Valid C declarations have at most one
+ * storage-class specifier. */
+ rc = explain_storage(buf, n, c->type);
+ break;
+ }
+ }
+
+ if (funcmap & (1ul << (CDECL_FUNC_INLINE & 0xff))) {
+ ret += cdecl__advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "inline");
+ }
+
+ return ret + rc;
+}
+
+size_t cdecl__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 += cdecl__advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "restrict");
+ }
+ if (qualmap & (1ul << (CDECL_QUAL_VOLATILE & 0xff))) {
+ ret += cdecl__advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "volatile");
+ }
+ if (qualmap & (1ul << (CDECL_QUAL_CONST & 0xff))) {
+ ret += cdecl__advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "const");
+ }
+
+ return ret + rc;
+}
+
+/* Renders the type qualifiers and type specifiers in canonical form. */
+size_t cdecl__explain_post_specs(char *buf, size_t n, struct cdecl_declspec *s)
+{
+ const char *tag = NULL;
+ 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) {
+ if (cdecl_spec_kind(c) != CDECL_SPEC_TYPE)
+ continue;
+
+ /* Valid C types have at most one identifier. */
+ if (c->ident)
+ tag = c->ident;
+ }
+
+ rc = cdecl__explain_qualifiers(buf, n, s);
+ ret += cdecl__advance(&buf, &n, rc);
+
+ rc = snprintf(buf, n, "%s", cdecl__explain_typemap(typemap));
+ if (tag) {
+ ret += cdecl__advance(&buf, &n, rc);
+ rc = snprintf(buf, n, "%s", tag);
+ }
+
+ return ret + rc;
+}