/*
* 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);
}