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); }