2 * Render C declarations.
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/>.
25 static size_t declare_specs(char *buf, size_t n, struct cdecl_declspec *s)
32 rc = cdecl__explain_pre_specs(buf, n, s);
33 ret += cdecl__advance(&buf, &n, rc);
35 rc = cdecl__explain_post_specs(buf, n, s);
40 declare_declarator(char *buf, size_t n, struct cdecl_declarator *d);
42 static size_t declare_decl(char *buf, size_t n, struct cdecl *decl)
46 rc = declare_specs(buf, n, decl->specifiers);
47 if (decl->declarators->type != CDECL_DECL_NULL)
48 ret += cdecl__advance(&buf, &n, rc);
50 ret += cdecl__advance_(&buf, &n, rc);
52 return ret + declare_declarator(buf, n, decl->declarators);
56 declare_postfix_child(char *buf, size_t n, struct cdecl_declarator *d)
60 if (d->type == CDECL_DECL_POINTER) {
61 rc = snprintf(buf, n, "(");
62 ret += cdecl__advance_(&buf, &n, rc);
65 rc = declare_declarator(buf, n, d);
66 ret += cdecl__advance_(&buf, &n, rc);
68 if (d->type == CDECL_DECL_POINTER) {
69 rc = snprintf(buf, n, ")");
70 ret += cdecl__advance_(&buf, &n, rc);
76 static size_t declare_pointer(char *buf, size_t n, struct cdecl_pointer *p)
80 rc = snprintf(buf, n, "*");
82 ret += cdecl__advance(&buf, &n, rc);
84 ret += cdecl__advance_(&buf, &n, rc);
86 rc = cdecl__explain_specs(buf, n, p->qualifiers, CDECL_SPEC_QUAL);
87 return ret + cdecl__advance(&buf, &n, rc);
90 static size_t declare_array(char *buf, size_t n, struct cdecl_array *a)
94 rc = snprintf(buf, n, "[");
95 ret += cdecl__advance_(&buf, &n, rc);
98 rc = snprintf(buf, n, "%s", a->vla[0] ? a->vla : "*");
100 rc = snprintf(buf, n, "%.0ju", a->length);
101 ret += cdecl__advance_(&buf, &n, rc);
103 return ret + snprintf(buf, n, "]");
106 static size_t declare_function(char *buf, size_t n, struct cdecl_function *f)
110 rc = snprintf(buf, n, "(");
111 ret += cdecl__advance_(&buf, &n, rc);
113 for (struct cdecl *p = f->parameters; p; p = p->next) {
114 rc = declare_decl(buf, n, p);
115 ret += cdecl__advance_(&buf, &n, rc);
119 rc = snprintf(buf, n, ", ");
120 else if (f->variadic)
121 rc = snprintf(buf, n, ", ...");
122 ret += cdecl__advance_(&buf, &n, rc);
125 return ret + snprintf(buf, n, ")");
129 declare_declarator(char *buf, size_t n, struct cdecl_declarator *d)
133 for (; d; d = d->child) {
135 case CDECL_DECL_NULL:
137 case CDECL_DECL_IDENT:
138 rc = snprintf(buf, n, "%s", d->u.ident);
139 ret += cdecl__advance_(&buf, &n, rc);
141 case CDECL_DECL_POINTER:
142 rc = declare_pointer(buf, n, &d->u.pointer);
143 ret += cdecl__advance_(&buf, &n, rc);
146 * Arrays and functions are special: since they are postfix,
147 * we need to render the children before rendering their
150 case CDECL_DECL_ARRAY:
151 rc = declare_postfix_child(buf, n, d->child);
152 ret += cdecl__advance_(&buf, &n, rc);
153 return ret + declare_array(buf, n, &d->u.array);
154 case CDECL_DECL_FUNCTION:
155 rc = declare_postfix_child(buf, n, d->child);
156 ret += cdecl__advance_(&buf, &n, rc);
157 return ret + declare_function(buf, n, &d->u.function);
166 size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl)
168 return declare_decl(buf, n, decl);