2 * Normalize C declaration specifier lists.
3 * Copyright © 2011 Nick Bowler
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "normalize.h"
26 * Totally order the declaration specifier types by defining an injection into
27 * the natural numbers.
29 static unsigned order_spec(struct cdecl_declspec *spec)
32 # include "ordspecs.h"
38 static int compare_specs(struct cdecl_declspec *a, struct cdecl_declspec *b)
40 return order_spec(a) - order_spec(b);
44 * Merge two sorted specifier lists. Each list must have at least one element.
46 static struct cdecl_declspec *
47 merge_specs(struct cdecl_declspec *l1, size_t n1,
48 struct cdecl_declspec *l2, size_t n2)
50 struct cdecl_declspec *top = l1, **p = ⊤
52 assert(n1 > 0 && n2 > 0);
54 for (size_t i = 0, j = 0; i < n1 && j < n2;) {
55 int ord = compare_specs(l1, l2);
56 struct cdecl_declspec *tmp;
81 * A simple merge sort. Set n to the number of elements in the list, or 0
82 * to have the sort function count them.
84 static struct cdecl_declspec *sort_specs(struct cdecl_declspec *l1, size_t n)
86 struct cdecl_declspec *l2, *c;
89 /* Find the midpoint of the list. */
91 for (i = 0, l2 = l1; i < (n+1)/2; i++)
94 for (i = 0, c = l2 = l1; c; i++, c = c->next) {
108 /* l1 always has the longer "half". */
109 l1 = sort_specs(l1, (n+1)/2);
110 l2 = sort_specs(l2, n/2);
112 return merge_specs(l1, (n+1)/2, l2, n/2);
116 * C allows declaration specifiers to appear in any order, and allows arbitrary
117 * repetition of some kinds of specifiers. Normalize the specifier lists by
118 * sorting the specifiers and removing repeated function specifiers and type
121 struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs)
123 struct cdecl_declspec *c, *l;
128 specs = sort_specs(specs, 0);
130 for (c = specs, l = NULL; c; l = c, c = c->next) {
131 switch (cdecl_spec_kind(c)) {
132 case CDECL_SPEC_QUAL:
133 case CDECL_SPEC_FUNC:
134 if (l && l->type == c->type) {