/* * Helper functions for outputting text. * Copyright © 2011 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "typemap.h" #include "output.h" #include "cdecl.h" size_t cdecl__advance_(char **buf, size_t *n, size_t amount) { if (amount >= *n) { *n = 0; *buf = 0; } else { *buf += amount; *n -= amount; } return amount; } size_t cdecl__advance(char **buf, size_t *n, size_t amount) { size_t ret, rc; if (!amount) return 0; ret = cdecl__advance_(buf, n, amount); rc = snprintf(*buf, *n, " "); return ret + cdecl__advance_(buf, n, rc); } static size_t explain_spec(char *buf, size_t n, struct cdecl_declspec *s) { switch (s->type) { /* Function specifiers */ case CDECL_FUNC_INLINE: return snprintf(buf, n, "inline"); /* Storage-class specifiers */ case CDECL_STOR_TYPEDEF: return snprintf(buf, n, "typedef"); case CDECL_STOR_EXTERN: return snprintf(buf, n, "extern"); case CDECL_STOR_STATIC: return snprintf(buf, n, "static"); case CDECL_STOR_AUTO: return snprintf(buf, n, "auto"); case CDECL_STOR_REGISTER: return snprintf(buf, n, "register"); /* Type qualifiers */ case CDECL_QUAL_RESTRICT: return snprintf(buf, n, "restrict"); case CDECL_QUAL_VOLATILE: return snprintf(buf, n, "volatile"); case CDECL_QUAL_CONST: return snprintf(buf, n, "const"); /* Type specifiers */ case CDECL_TYPE_VOID: return snprintf(buf, n, "void"); case CDECL_TYPE_CHAR: return snprintf(buf, n, "char"); case CDECL_TYPE_SHORT: return snprintf(buf, n, "short"); case CDECL_TYPE_INT: return snprintf(buf, n, "int"); case CDECL_TYPE_LONG: return snprintf(buf, n, "long"); case CDECL_TYPE_FLOAT: return snprintf(buf, n, "float"); case CDECL_TYPE_DOUBLE: return snprintf(buf, n, "double"); case CDECL_TYPE_SIGNED: return snprintf(buf, n, "signed"); case CDECL_TYPE_UNSIGNED: return snprintf(buf, n, "unsigned"); case CDECL_TYPE_BOOL: return snprintf(buf, n, "_Bool"); case CDECL_TYPE_COMPLEX: return snprintf(buf, n, "_Complex"); case CDECL_TYPE_IMAGINARY: return snprintf(buf, n, "_Imaginary"); case CDECL_TYPE_STRUCT: return snprintf(buf, n, "struct %s", s->ident); case CDECL_TYPE_UNION: return snprintf(buf, n, "union %s", s->ident); case CDECL_TYPE_ENUM: return snprintf(buf, n, "enum %s", s->ident); case CDECL_TYPE_IDENT: return snprintf(buf, n, "%s", s->ident); default: assert(0); } } /* * Render a list of declaration specifiers. Only the declaration specifiers * listed in mask, which is the bitwise OR of the desired specifier kinds, are * printed. */ size_t cdecl__explain_specs(char *buf, size_t n, struct cdecl_declspec *s, unsigned mask) { size_t ret = 0, rc = 0; for (struct cdecl_declspec *c = s; c; c = c->next) { switch (cdecl_spec_kind(c) & mask) { case CDECL_SPEC_FUNC: case CDECL_SPEC_STOR: case CDECL_SPEC_QUAL: case CDECL_SPEC_TYPE: ret += cdecl__advance(&buf, &n, rc); rc = explain_spec(buf, n, c); } } return ret + rc; } /* Renders the storage-class and function specifiers in canonical form. */ size_t cdecl__explain_pre_specs(char *buf, size_t n, struct cdecl_declspec *s) { return cdecl__explain_specs(buf, n, s, CDECL_SPEC_FUNC|CDECL_SPEC_STOR); } /* Renders the type qualifiers and type specifiers in canonical form. */ size_t cdecl__explain_post_specs(char *buf, size_t n, struct cdecl_declspec *s) { return cdecl__explain_specs(buf, n, s, CDECL_SPEC_QUAL|CDECL_SPEC_TYPE); }