/* * 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 const char *explain_spec_simple(struct cdecl_declspec *s) { switch (s->type) { # include "namespecs.h" } assert(0); } static size_t explain_spec(char *buf, size_t n, struct cdecl_declspec *s) { const char *keyword = explain_spec_simple(s); if (keyword[0] && s->ident) return snprintf(buf, n, "%s %s", keyword, s->ident); else if (s->ident) return snprintf(buf, n, "%s", s->ident); return snprintf(buf, n, "%s", keyword); } /* * 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); }