]> git.draconx.ca Git - cdecl99.git/blob - src/declare.c
Add support for outputting declarations as C code.
[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                 if (p->next)
100                         rc = snprintf(buf, n, ", ");
101                 else if (f->variadic)
102                         rc = snprintf(buf, n, ", ...)");
103                 else
104                         rc = snprintf(buf, n, ")");
105                 ret += cdecl__advance_(&buf, &n, rc);
106         }
107
108         return ret;
109 }
110
111 static size_t
112 declare_declarator(char *buf, size_t n, struct cdecl_declarator *d)
113 {
114         size_t ret = 0, rc;
115
116         for (; d; d = d->child) {
117                 switch (d->type) {
118                 case CDECL_DECL_NULL:
119                         break;
120                 case CDECL_DECL_IDENT:
121                         rc = snprintf(buf, n, "%s", d->u.ident);
122                         ret += cdecl__advance_(&buf, &n, rc);
123                         break;
124                 case CDECL_DECL_POINTER:
125                         rc = declare_pointer(buf, n, &d->u.pointer);
126                         ret += cdecl__advance_(&buf, &n, rc);
127                         break;
128                 /*
129                  * Arrays and functions are special: since they are postfix,
130                  * we need to render the children before rendering their
131                  * "bodies".
132                  */
133                 case CDECL_DECL_ARRAY:
134                         rc = declare_postfix_child(buf, n, d->child);
135                         ret += cdecl__advance_(&buf, &n, rc);
136                         return ret + declare_array(buf, n, &d->u.array);
137                 case CDECL_DECL_FUNCTION:
138                         rc = declare_postfix_child(buf, n, d->child);
139                         ret += cdecl__advance_(&buf, &n, rc);
140                         return ret + declare_function(buf, n, &d->u.function);
141                 default:
142                         assert(0);
143                 }
144         }
145
146         return ret;
147 }
148
149 size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl)
150 {
151         return declare_decl(buf, n, decl);
152 }