/* * Main command implementation routines for cdecl99. * Copyright © 2011-2012, 2020-2021 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) { fprintf(stderr, "%s\n", _("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) { err = cdecl_get_error(); fprintf(stderr, "%s\n", err->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) { err = cdecl_get_error(); fprintf(stderr, "%s\n", err->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) { const struct cdecl_error *err; struct cdecl *decl; const char *str; int ret = -1; /* The name of the command is significant here. */ decl = cdecl_parse_english(cmd); if (!decl) { err = cdecl_get_error(); fprintf(stderr, "%s\n", err->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; }