]> git.draconx.ca Git - cdecl99.git/blob - src/declare.c
Fix rendering of non-prototype function declarations.
[cdecl99.git] / src / declare.c
1 #include <stdio.h>
2 #include <assert.h>
3
4 #include "cdecl.h"
5 #include "output.h"
6
7 static size_t declare_specs(char *buf, size_t n, struct cdecl_declspec *s)
8 {
9         size_t ret = 0, rc;
10
11         if (!s)
12                 return 0;
13
14         rc = cdecl__explain_pre_specs(buf, n, s);
15         ret += cdecl__advance(&buf, &n, rc);
16
17         rc = cdecl__explain_post_specs(buf, n, s);
18         return ret + rc;
19 }
20
21 static size_t
22 declare_declarator(char *buf, size_t n, struct cdecl_declarator *d);
23
24 static size_t declare_decl(char *buf, size_t n, struct cdecl *decl)
25 {
26         size_t ret = 0, rc;
27
28         rc = declare_specs(buf, n, decl->specifiers);
29         if (decl->declarators->type != CDECL_DECL_NULL)
30                 ret += cdecl__advance(&buf, &n, rc);
31         else
32                 ret += cdecl__advance_(&buf, &n, rc);
33
34         return ret + declare_declarator(buf, n, decl->declarators);
35 }
36
37 static size_t
38 declare_postfix_child(char *buf, size_t n, struct cdecl_declarator *d)
39 {
40         size_t ret = 0, rc;
41
42         if (d->type == CDECL_DECL_POINTER) {
43                 rc = snprintf(buf, n, "(");
44                 ret += cdecl__advance_(&buf, &n, rc);
45         }
46
47         rc = declare_declarator(buf, n, d);
48         ret += cdecl__advance_(&buf, &n, rc);
49
50         if (d->type == CDECL_DECL_POINTER) {
51                 rc = snprintf(buf, n, ")");
52                 ret += cdecl__advance_(&buf, &n, rc);
53         }
54
55         return ret;
56 }
57
58 static size_t declare_pointer(char *buf, size_t n, struct cdecl_pointer *p)
59 {
60         size_t ret = 0, rc;
61
62         rc = snprintf(buf, n, "*");
63         if (p->qualifiers)
64                 ret += cdecl__advance(&buf, &n, rc);
65         else
66                 ret += cdecl__advance_(&buf, &n, rc);
67
68         rc = cdecl__explain_qualifiers(buf, n, p->qualifiers);
69         return ret + cdecl__advance(&buf, &n, rc);
70 }
71
72 static size_t declare_array(char *buf, size_t n, struct cdecl_array *a)
73 {
74         size_t ret = 0, rc;
75
76         rc = snprintf(buf, n, "[");
77         ret += cdecl__advance_(&buf, &n, rc);
78
79         if (a->vla)
80                 rc = snprintf(buf, n, "%s", a->vla[0] ? a->vla : "*");
81         else
82                 rc = snprintf(buf, n, "%.0ju", a->length);
83         ret += cdecl__advance_(&buf, &n, rc);
84
85         return ret + snprintf(buf, n, "]");
86 }
87
88 static size_t declare_function(char *buf, size_t n, struct cdecl_function *f)
89 {
90         size_t ret = 0, rc;
91
92         rc = snprintf(buf, n, "(");
93         ret += cdecl__advance_(&buf, &n, rc);
94
95         for (struct cdecl *p = f->parameters; p; p = p->next) {
96                 rc = declare_decl(buf, n, p);
97                 ret += cdecl__advance_(&buf, &n, rc);
98
99                 rc = 0;
100                 if (p->next)
101                         rc = snprintf(buf, n, ", ");
102                 else if (f->variadic)
103                         rc = snprintf(buf, n, ", ...");
104                 ret += cdecl__advance_(&buf, &n, rc);
105         }
106
107         return ret + snprintf(buf, n, ")");
108 }
109
110 static size_t
111 declare_declarator(char *buf, size_t n, struct cdecl_declarator *d)
112 {
113         size_t ret = 0, rc;
114
115         for (; d; d = d->child) {
116                 switch (d->type) {
117                 case CDECL_DECL_NULL:
118                         break;
119                 case CDECL_DECL_IDENT:
120                         rc = snprintf(buf, n, "%s", d->u.ident);
121                         ret += cdecl__advance_(&buf, &n, rc);
122                         break;
123                 case CDECL_DECL_POINTER:
124                         rc = declare_pointer(buf, n, &d->u.pointer);
125                         ret += cdecl__advance_(&buf, &n, rc);
126                         break;
127                 /*
128                  * Arrays and functions are special: since they are postfix,
129                  * we need to render the children before rendering their
130                  * "bodies".
131                  */
132                 case CDECL_DECL_ARRAY:
133                         rc = declare_postfix_child(buf, n, d->child);
134                         ret += cdecl__advance_(&buf, &n, rc);
135                         return ret + declare_array(buf, n, &d->u.array);
136                 case CDECL_DECL_FUNCTION:
137                         rc = declare_postfix_child(buf, n, d->child);
138                         ret += cdecl__advance_(&buf, &n, rc);
139                         return ret + declare_function(buf, n, &d->u.function);
140                 default:
141                         assert(0);
142                 }
143         }
144
145         return ret;
146 }
147
148 size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl)
149 {
150         return declare_decl(buf, n, decl);
151 }