X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/31ac11cc668bb8ecc1317fd2e8bd79b7925bceeb..bbfdea24b2b940031e86e990bc457785dd378b58:/src/normalize.c
diff --git a/src/normalize.c b/src/normalize.c
index 704d575..eac71f3 100644
--- a/src/normalize.c
+++ b/src/normalize.c
@@ -1,6 +1,6 @@
/*
* Normalize C declaration specifier lists.
- * Copyright © 2011 Nick Bowler
+ * Copyright © 2011, 2021 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,27 +15,51 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+
#include
#include
#include
#include "cdecl.h"
-#include "normalize.h"
+#include "cdecl-internal.h"
/*
- * Totally order the declaration specifier types by defining an injection into
- * the natural numbers.
+ * Partially order the declaration specifiers by assigning each specifier
+ * type an appropriate integer value. These values need not be unique for
+ * specifiers that never appear together.
+ *
+ * This implementation relies implicitly on the specific enumeration values.
+ * These values are expected to be stable as they are exposed library API.
*/
-static unsigned order_spec(struct cdecl_declspec *spec)
+static int order_spec(const struct cdecl_declspec *spec)
{
- switch (spec->type) {
-# include "ordspecs.h"
- default:
- assert(0);
+ unsigned kind = cdecl_spec_kind(spec);
+ unsigned ret = spec->type;
+
+ /* General sequence: storage, function, qualifier, type */
+ switch (kind) {
+ case CDECL_SPEC_QUAL:
+ ret |= CDECL_SPEC_FUNC;
+ break;
+ case CDECL_SPEC_TYPE:
+ /* Manually reorder some elements that are in the wrong place */
+ switch (ret) {
+ case CDECL_TYPE_INT:
+ ret += 2; /* OK because "float int" is invalid. */
+ break;
+ case CDECL_TYPE_SIGNED:
+ case CDECL_TYPE_UNSIGNED:
+ ret = CDECL_TYPE_VOID;
+ break;
+ }
+ ret |= CDECL_SPEC_FUNC|CDECL_SPEC_QUAL;
}
+
+ return ret;
}
-static int compare_specs(struct cdecl_declspec *a, struct cdecl_declspec *b)
+static int compare_specs(const struct cdecl_declspec *a,
+ const struct cdecl_declspec *b)
{
return order_spec(a) - order_spec(b);
}