]> git.draconx.ca Git - cdecl99.git/blob - src/declare.c
Include config.h in all C source files.
[cdecl99.git] / src / declare.c
1 #include <config.h>
2 #include <stdio.h>
3 #include <assert.h>
4
5 #include "cdecl.h"
6 #include "output.h"
7
8 static size_t declare_specs(char *buf, size_t n, struct cdecl_declspec *s)
9 {
10         size_t ret = 0, rc;
11
12         if (!s)
13                 return 0;
14
15         rc = cdecl__explain_pre_specs(buf, n, s);
16         ret += cdecl__advance(&buf, &n, rc);
17
18         rc = cdecl__explain_post_specs(buf, n, s);
19         return ret + rc;
20 }
21
22 static size_t
23 declare_declarator(char *buf, size_t n, struct cdecl_declarator *d);
24
25 static size_t declare_decl(char *buf, size_t n, struct cdecl *decl)
26 {
27         size_t ret = 0, rc;
28
29         rc = declare_specs(buf, n, decl->specifiers);
30         if (decl->declarators->type != CDECL_DECL_NULL)
31                 ret += cdecl__advance(&buf, &n, rc);
32         else
33                 ret += cdecl__advance_(&buf, &n, rc);
34
35         return ret + declare_declarator(buf, n, decl->declarators);
36 }
37
38 static size_t
39 declare_postfix_child(char *buf, size_t n, struct cdecl_declarator *d)
40 {
41         size_t ret = 0, rc;
42
43         if (d->type == CDECL_DECL_POINTER) {
44                 rc = snprintf(buf, n, "(");
45                 ret += cdecl__advance_(&buf, &n, rc);
46         }
47
48         rc = declare_declarator(buf, n, d);
49         ret += cdecl__advance_(&buf, &n, rc);
50
51         if (d->type == CDECL_DECL_POINTER) {
52                 rc = snprintf(buf, n, ")");
53                 ret += cdecl__advance_(&buf, &n, rc);
54         }
55
56         return ret;
57 }
58
59 static size_t declare_pointer(char *buf, size_t n, struct cdecl_pointer *p)
60 {
61         size_t ret = 0, rc;
62
63         rc = snprintf(buf, n, "*");
64         if (p->qualifiers)
65                 ret += cdecl__advance(&buf, &n, rc);
66         else
67                 ret += cdecl__advance_(&buf, &n, rc);
68
69         rc = cdecl__explain_qualifiers(buf, n, p->qualifiers);
70         return ret + cdecl__advance(&buf, &n, rc);
71 }
72
73 static size_t declare_array(char *buf, size_t n, struct cdecl_array *a)
74 {
75         size_t ret = 0, rc;
76
77         rc = snprintf(buf, n, "[");
78         ret += cdecl__advance_(&buf, &n, rc);
79
80         if (a->vla)
81                 rc = snprintf(buf, n, "%s", a->vla[0] ? a->vla : "*");
82         else
83                 rc = snprintf(buf, n, "%.0ju", a->length);
84         ret += cdecl__advance_(&buf, &n, rc);
85
86         return ret + snprintf(buf, n, "]");
87 }
88
89 static size_t declare_function(char *buf, size_t n, struct cdecl_function *f)
90 {
91         size_t ret = 0, rc;
92
93         rc = snprintf(buf, n, "(");
94         ret += cdecl__advance_(&buf, &n, rc);
95
96         for (struct cdecl *p = f->parameters; p; p = p->next) {
97                 rc = declare_decl(buf, n, p);
98                 ret += cdecl__advance_(&buf, &n, rc);
99
100                 rc = 0;
101                 if (p->next)
102                         rc = snprintf(buf, n, ", ");
103                 else if (f->variadic)
104                         rc = snprintf(buf, n, ", ...");
105                 ret += cdecl__advance_(&buf, &n, rc);
106         }
107
108         return ret + snprintf(buf, n, ")");
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 }