]> git.draconx.ca Git - cdecl99.git/blob - src/output.c
Separate specifier handling from the output routines.
[cdecl99.git] / src / output.c
1 /*
2  *  Helper functions for outputting text.
3  *  Copyright © 2011 Nick Bowler
4  *
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.
9  *
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.
14  *
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/>.
17  */
18 #include <config.h>
19 #include <stdio.h>
20 #include <assert.h>
21
22 #include "typemap.h"
23 #include "output.h"
24 #include "cdecl.h"
25
26 size_t cdecl__advance_(char **buf, size_t *n, size_t amount)
27 {
28         if (amount >= *n) {
29                 *n   = 0;
30                 *buf = 0;
31         } else {
32                 *buf += amount;
33                 *n   -= amount;
34         }
35
36         return amount;
37 }
38
39 size_t cdecl__advance(char **buf, size_t *n, size_t amount)
40 {
41         size_t ret, rc;
42
43         if (!amount)
44                 return 0;
45
46         ret = cdecl__advance_(buf, n, amount);
47         rc = snprintf(*buf, *n, " ");
48         return ret + cdecl__advance_(buf, n, rc);
49 }
50
51 static size_t explain_spec(char *buf, size_t n, struct cdecl_declspec *s)
52 {
53         switch (s->type) {
54         /* Function specifiers */
55         case CDECL_FUNC_INLINE:
56                 return snprintf(buf, n, "inline");
57         /* Storage-class specifiers */
58         case CDECL_STOR_TYPEDEF:
59                 return snprintf(buf, n, "typedef");
60         case CDECL_STOR_EXTERN:
61                 return snprintf(buf, n, "extern");
62         case CDECL_STOR_STATIC:
63                 return snprintf(buf, n, "static");
64         case CDECL_STOR_AUTO:
65                 return snprintf(buf, n, "auto");
66         case CDECL_STOR_REGISTER:
67                 return snprintf(buf, n, "register");
68         /* Type qualifiers */
69         case CDECL_QUAL_RESTRICT:
70                 return snprintf(buf, n, "restrict");
71         case CDECL_QUAL_VOLATILE:
72                 return snprintf(buf, n, "volatile");
73         case CDECL_QUAL_CONST:
74                 return snprintf(buf, n, "const");
75         /* Type specifiers */
76         case CDECL_TYPE_VOID:
77                 return snprintf(buf, n, "void");
78         case CDECL_TYPE_CHAR:
79                 return snprintf(buf, n, "char");
80         case CDECL_TYPE_SHORT:
81                 return snprintf(buf, n, "short");
82         case CDECL_TYPE_INT:
83                 return snprintf(buf, n, "int");
84         case CDECL_TYPE_LONG:
85                 return snprintf(buf, n, "long");
86         case CDECL_TYPE_FLOAT:
87                 return snprintf(buf, n, "float");
88         case CDECL_TYPE_DOUBLE:
89                 return snprintf(buf, n, "double");
90         case CDECL_TYPE_SIGNED:
91                 return snprintf(buf, n, "signed");
92         case CDECL_TYPE_UNSIGNED:
93                 return snprintf(buf, n, "unsigned");
94         case CDECL_TYPE_BOOL:
95                 return snprintf(buf, n, "_Bool");
96         case CDECL_TYPE_COMPLEX:
97                 return snprintf(buf, n, "_Complex");
98         case CDECL_TYPE_IMAGINARY:
99                 return snprintf(buf, n, "_Imaginary");
100         case CDECL_TYPE_STRUCT:
101                 return snprintf(buf, n, "struct %s", s->ident);
102         case CDECL_TYPE_UNION:
103                 return snprintf(buf, n, "union %s", s->ident);
104         case CDECL_TYPE_ENUM:
105                 return snprintf(buf, n, "enum %s", s->ident);
106         case CDECL_TYPE_IDENT:
107                 return snprintf(buf, n, "%s", s->ident);
108         default:
109                 assert(0);
110         }
111 }
112
113 /*
114  * Render a list of declaration specifiers.  Only the declaration specifiers
115  * listed in mask, which is the bitwise OR of the desired specifier kinds, are
116  * printed.
117  */
118 size_t cdecl__explain_specs(char *buf, size_t n, struct cdecl_declspec *s,
119                                                  unsigned mask)
120 {
121         size_t ret = 0, rc = 0;
122
123         for (struct cdecl_declspec *c = s; c; c = c->next) {
124                 switch (cdecl_spec_kind(c) & mask) {
125                 case CDECL_SPEC_FUNC:
126                 case CDECL_SPEC_STOR:
127                 case CDECL_SPEC_QUAL:
128                 case CDECL_SPEC_TYPE:
129                         ret += cdecl__advance(&buf, &n, rc);
130                         rc = explain_spec(buf, n, c);
131                 }
132         }
133
134         return ret + rc;
135 }
136
137 /* Renders the storage-class and function specifiers in canonical form. */
138 size_t cdecl__explain_pre_specs(char *buf, size_t n, struct cdecl_declspec *s)
139 {
140         return cdecl__explain_specs(buf, n, s, CDECL_SPEC_FUNC|CDECL_SPEC_STOR);
141 }
142
143 /* Renders the type qualifiers and type specifiers in canonical form. */
144 size_t cdecl__explain_post_specs(char *buf, size_t n, struct cdecl_declspec *s)
145 {
146         return cdecl__explain_specs(buf, n, s, CDECL_SPEC_QUAL|CDECL_SPEC_TYPE);
147 }