]> git.draconx.ca Git - cdecl99.git/blobdiff - src/output.c
Add nodefault to flex options.
[cdecl99.git] / src / output.c
index 8c2cd0b6b1b4e9b9fe2d2934f6538d95abdb4be4..3d0a9236532a8953e05553cd22f3340f1fb43ef4 100644 (file)
@@ -1,5 +1,9 @@
 #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)
 {
@@ -25,3 +29,107 @@ 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;
+}