/*
* 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
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include <config.h>
#include <stdlib.h>
#include <assert.h>
#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);
}