/*
* Main command implementation routines for cdecl99.
* Copyright © 2011-2012, 2020-2021, 2023 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 "cdecl99.h"
#include "cdecl.h"
/*
* Format a declaration according to the given function and return a pointer
* to the formatted string. The returned pointer remains valid until the
* next call, after which it must not be re-used.
*
* Returns NULL on failure.
*/
static const char *
do_format(size_t func(char *, size_t, struct cdecl *), struct cdecl *decl)
{
static size_t bufsz;
static char *buf;
size_t rc;
retry:
rc = func(buf, bufsz, decl);
if (rc >= bufsz) {
char *tmp;
tmp = realloc(buf, rc + 1);
if (!tmp) {
print_error("%s", _("failed to allocate memory"));
return NULL;
}
buf = tmp;
bufsz = rc + 1;
goto retry;
}
return buf;
}
int run_command_explain(const char *arg)
{
const struct cdecl_error *err;
struct cdecl *decl;
const char *str;
int ret = -1;
decl = cdecl_parse_decl(arg);
if (!decl) {
print_error("%s", cdecl_get_error()->str);
goto out;
}
for (struct cdecl *i = decl; i; i = i->next) {
str = do_format(cdecl_explain, i);
if (!str)
goto out;
printf("%s\n", str);
}
ret = 0;
out:
cdecl_free(decl);
return ret;
}
int run_command_simplify(const char *arg)
{
const struct cdecl_error *err;
struct cdecl *decl;
const char *str;
int ret = -1;
decl = cdecl_parse_decl(arg);
if (!decl) {
print_error("%s", cdecl_get_error()->str);
goto out;
}
for (struct cdecl *i = decl; i; i = i->next) {
struct cdecl_declspec *s = i->specifiers;
if (i != decl) {
i->specifiers = NULL;
printf(", ");
}
str = do_format(cdecl_declare, i);
i->specifiers = s;
if (!str)
goto out;
printf("%s", str);
}
putchar('\n');
ret = 0;
out:
cdecl_free(decl);
return ret;
}
int run_command_declare(const char *cmd)
{
struct cdecl *decl;
const char *str;
int ret = -1;
/* The name of the command is significant here. */
decl = cdecl_parse_english(cmd);
if (!decl) {
print_error("%s", cdecl_get_error()->str);
goto out;
}
/*
* English parses have at most one full declarator, so no loop is
* needed here.
*/
str = do_format(cdecl_declare, decl);
if (!str)
goto out;
printf("%s\n", str);
ret = 0;
out:
cdecl_free(decl);
return ret;
}