2 * Helper functions for outputting text.
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/>.
26 size_t cdecl__advance_(char **buf, size_t *n, size_t amount)
39 size_t cdecl__advance(char **buf, size_t *n, size_t amount)
46 ret = cdecl__advance_(buf, n, amount);
47 rc = snprintf(*buf, *n, " ");
48 return ret + cdecl__advance_(buf, n, rc);
51 static size_t explain_storage(char *buf, size_t n, unsigned spec)
54 case CDECL_STOR_TYPEDEF:
55 return snprintf(buf, n, "typedef");
56 case CDECL_STOR_EXTERN:
57 return snprintf(buf, n, "extern");
58 case CDECL_STOR_STATIC:
59 return snprintf(buf, n, "static");
61 return snprintf(buf, n, "auto");
62 case CDECL_STOR_REGISTER:
63 return snprintf(buf, n, "register");
69 /* Renders the storage-class and function specifiers in canonical form. */
70 size_t cdecl__explain_pre_specs(char *buf, size_t n, struct cdecl_declspec *s)
72 unsigned long funcmap = 0;
73 size_t ret = 0, rc = 0;
75 for (struct cdecl_declspec *c = s; c; c = c->next) {
76 switch (cdecl_spec_kind(c)) {
78 funcmap |= 1ul << (c->type & 0xff);
81 /* Valid C declarations have at most one
82 * storage-class specifier. */
83 rc = explain_storage(buf, n, c->type);
88 if (funcmap & (1ul << (CDECL_FUNC_INLINE & 0xff))) {
89 ret += cdecl__advance(&buf, &n, rc);
90 rc = snprintf(buf, n, "inline");
96 size_t cdecl__explain_qualifiers(char *buf, size_t n, struct cdecl_declspec *s)
98 unsigned long qualmap = 0;
99 size_t ret = 0, rc = 0;
101 for (struct cdecl_declspec *c = s; c; c = c->next) {
102 if (cdecl_spec_kind(c) != CDECL_SPEC_QUAL)
104 qualmap |= 1ul << (c->type & 0xff);
107 if (qualmap & (1ul << (CDECL_QUAL_RESTRICT & 0xff))) {
108 ret += cdecl__advance(&buf, &n, rc);
109 rc = snprintf(buf, n, "restrict");
111 if (qualmap & (1ul << (CDECL_QUAL_VOLATILE & 0xff))) {
112 ret += cdecl__advance(&buf, &n, rc);
113 rc = snprintf(buf, n, "volatile");
115 if (qualmap & (1ul << (CDECL_QUAL_CONST & 0xff))) {
116 ret += cdecl__advance(&buf, &n, rc);
117 rc = snprintf(buf, n, "const");
123 /* Renders the type qualifiers and type specifiers in canonical form. */
124 size_t cdecl__explain_post_specs(char *buf, size_t n, struct cdecl_declspec *s)
126 const char *tag = NULL;
127 unsigned long typemap;
130 typemap = cdecl__build_typemap(s);
134 for (struct cdecl_declspec *c = s; c; c = c->next) {
135 if (cdecl_spec_kind(c) != CDECL_SPEC_TYPE)
138 /* Valid C types have at most one identifier. */
143 rc = cdecl__explain_qualifiers(buf, n, s);
144 ret += cdecl__advance(&buf, &n, rc);
146 rc = snprintf(buf, n, "%s", cdecl__explain_typemap(typemap));
148 ret += cdecl__advance(&buf, &n, rc);
149 rc = snprintf(buf, n, "%s", tag);