-no-undefined -version-info 1:0:0
libcdecl_la_SOURCES = src/scan.c src/parse.c src/parse-decl.c src/output.c \
src/explain.c src/declare.c src/error.c src/normalize.c \
- src/cdecl-internal.h
+ src/cdecl-internal.h src/errmsg.h
libcdecl_la_LIBADD = $(shared_gl_objects) $(LTLIBINTL) $(LIBTHREAD)
EXTRA_libcdecl_la_DEPENDENCIES = $(shared_gl_objects)
$(libcdecl_la_OBJECTS): $(gnulib_headers)
bin_PROGRAMS = cdecl99
cdecl99_SOURCES = common/src/help.c src/commands.c src/cdecl99.h
-cdecl99_LDADD = $(libmain_a_OBJECTS) $(libexec_a_OBJECTS) libcdecl.la \
- libgnu.a $(LTLIBINTL) $(LTLIBREADLINE)
+EXTRA_cdecl99_DEPENDENCIES = $(libmain_a_OBJECTS) $(libexec_a_OBJECTS)
+cdecl99_LDADD = $(EXTRA_cdecl99_DEPENDENCIES) libcdecl.la libgnu.a \
+ $(LTLIBINTL) $(LTLIBREADLINE)
$(cdecl99_OBJECTS): $(gnulib_headers)
if USE_NLS
$(t_rng_test_OBJECTS): $(gnulib_headers)
EXTRA_DIST += t/xos256p.c
-src/parse.lo: src/scan.h
-src/scan.lo: src/parse.h
-src/parse-decl.lo: src/scan.h src/parse.h src/typemap.h
+src/parse.lo: src/scan.h src/errmsg.h
+src/scan.lo: src/parse.h src/errmsg.h
+src/parse-decl.lo: src/scan.h src/parse.h src/typemap.h src/errmsg.h
src/output.lo: src/specstr.h
+src/error.lo: src/errmsg.h
t/declgen.$(OBJEXT): t/typegen.h
+t/cdeclerr.$(OBJEXT): src/errmsg.h
check_PROGRAMS += t/cdeclerr
t_cdeclerr_SOURCES = common/src/tap.c t/cdeclerr.c
MAINTAINERCLEANFILES += $(OPTFILES:.opt=.h)
EXTRA_DIST += $(DX_BASEDIR)/scripts/gen-options.awk $(OPTFILES)
-STRFILES = src/commands.str
+STRFILES = src/commands.str src/errmsg.str
.str.h:
$(AM_V_GEN) $(AWK) -f $(DX_BASEDIR)/scripts/gen-strtab.awk $< >$@.tmp
$(AM_V_at) mv -f $@.tmp $@
/*
* Internal declarations for libcdecl.
- * Copyright © 2021 Nick Bowler
+ * Copyright © 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
}
#endif
-const char *cdecl__strerror(unsigned code);
-void cdecl__err(unsigned code, ...);
+void cdecl__err(unsigned code, const char *fmt, ...);
+void cdecl__errmsg(unsigned msg);
-unsigned long cdecl__build_typemap(struct cdecl_declspec *s);
struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs);
size_t cdecl__advance_(char **buf, size_t *n, size_t amount);
/*
- * Copyright © 2011 Nick Bowler
+ * Copyright © 2011, 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
enum {
CDECL_ENOMEM = 1,
CDECL_ENOPARSE,
+
+ /* Obsolete error codes (no longer returned by the library) */
CDECL_EBADARRAY,
CDECL_EBADDECL,
CDECL_EBADPARAMS,
#include <glthread/lock.h>
#include <glthread/tls.h>
+#include "errmsg.h"
+
gl_once_define(static, tls_initialized);
static gl_tls_key_t tls_key;
free(err);
}
+static void set_err(unsigned code, struct cdecl_error *err)
+{
+ static const char errmsgs[] = STRTAB_INITIALIZER;
+
+ switch (code) {
+ case CDECL__ENOMEM:
+ err->code = CDECL_ENOMEM;
+ break;
+ default:
+ err->code = CDECL_ENOPARSE;
+ break;
+ }
+
+ err->str = _(&errmsgs[code]);
+}
+
static void initialize(void)
{
cdecl__init_i18n();
- err_no_mem.str = _("failed to allocate memory");
+ set_err(CDECL__ENOMEM, &err_no_mem);
gl_tls_key_init(tls_key, free_err);
}
}
/*
- * cdecl__err(CDECL_ENOMEM);
- * cdecl__err(code, fmt, ...);
- *
+ * Set the library error to one of the preset messages defined in errmsg.h
+ * (CDECL__Exxx).
+ */
+void cdecl__errmsg(unsigned msg)
+{
+ struct err_state *state;
+
+ state = get_err_state();
+ if (!state)
+ return;
+
+ set_err(msg, &state->err);
+}
+
+/*
* Sets the library error to code, with a printf-style error string.
*/
-void cdecl__err(unsigned code, ...)
+void cdecl__err(unsigned code, const char *fmt, ...)
{
- const char *fmt;
struct err_state *state;
int rc, try = 0;
va_list ap;
if (!state)
return;
- if (code == CDECL_ENOMEM) {
- state->err.code = code;
- state->err.str = err_no_mem.str;
- return;
- }
retry:
- va_start(ap, code);
- fmt = va_arg(ap, const char *);
+ va_start(ap, fmt);
rc = vsnprintf(state->str, state->nstr, fmt, ap);
va_end(ap);
#include "cdecl-internal.h"
#include "parse.h"
#include "scan.h"
+#include "errmsg.h"
/*
* We can represent type specifiers as a bitmap, which gives us a finite
if (map & bit) {
if (bit == 1ul << MAP_LLONG_BIT)
- cdecl__err(CDECL_EBADTYPE, _("too many long specifiers"));
+ cdecl__errmsg(CDECL__ETOOLONG);
else
- cdecl__err(CDECL_EBADTYPE, _("duplicate type specifier"));
+ cdecl__errmsg(CDECL__EDUPTYPE);
return false;
}
map |= bit;
return true;
if (map == 0)
- cdecl__err(CDECL_EBADTYPE, _("no type specified"));
+ cdecl__errmsg(CDECL__ENOTYPE);
else
- cdecl__err(CDECL_EBADTYPE, _("invalid type specified"));
+ cdecl__errmsg(CDECL__EBADTYPE);
return false;
}
if (c->type == CDECL_TYPE_VOID &&
(d->type == CDECL_DECL_IDENT
|| d->type == CDECL_DECL_ARRAY)) {
- cdecl__err(CDECL_EBADTYPE, _("invalid declaration of type void"));
+ cdecl__errmsg(CDECL__EBADVOID);
return false;
}
continue;
case CDECL_SPEC_STOR:
if (top && abstract) {
- cdecl__err(CDECL_EBADSTOR, _("type names cannot have storage-class specifiers"));
+ cdecl__errmsg(CDECL__ETYPESTOR);
return false;
}
if (!top && c->type != CDECL_STOR_REGISTER) {
- cdecl__err(CDECL_EBADSTOR, _("function parameters may only have register storage"));
+ cdecl__errmsg(CDECL__EFUNCSTOR);
return false;
}
if (++num_storage > 1) {
- cdecl__err(CDECL_EBADSTOR, _("too many storage-class specifiers"));
+ cdecl__errmsg(CDECL__EMANYSTOR);
return false;
}
break;
* pointer qualifier list, which isn't checked here.
*/
if (c->type == CDECL_QUAL_RESTRICT) {
- cdecl__err(CDECL_EBADQUAL, _("only pointer types can be restrict-qualified"));
+ cdecl__errmsg(CDECL__EBADQUAL);
return false;
}
break;
case CDECL_SPEC_FUNC:
- if (abstract) {
- cdecl__err(CDECL_ENOTFUNC, _("type names cannot have function specifiers"));
+ if (abstract || !top || d->type != CDECL_DECL_FUNCTION) {
+ cdecl__errmsg(CDECL__ENOTFUNC);
return false;
}
- if (!top || d->type != CDECL_DECL_FUNCTION) {
- cdecl__err(CDECL_ENOTFUNC, _("only function declarations can have function specifiers"));
- return false;
- }
break;
default:
assert(0);
}
if (d->child->type != CDECL_DECL_NULL) {
- cdecl__err(CDECL_EBADPARAMS, _("invalid function parameter"));
+ cdecl__errmsg(CDECL__EBADPARAM);
return -1;
}
if (decl->type == CDECL_DECL_FUNCTION
&& decl->child->type == CDECL_DECL_NULL
&& !function_is_reducible(decl)) {
- cdecl__err(CDECL_EBADPARAMS, _("too many parentheses in function"));
+ cdecl__errmsg(CDECL__EMANYPAREN);
return -1;
}
continue;
if (spec != param->specifiers || spec->next != NULL) {
- cdecl__err(CDECL_EVOIDPARAM, _("void parameter cannot have extra specifiers"));
+ cdecl__errmsg(CDECL__EVOIDPARAM);
return -1;
} else if (d->u.function.parameters->next) {
- cdecl__err(CDECL_EVOIDPARAM, _("void parameter must stand alone"));
+ cdecl__errmsg(CDECL__EVOIDPARAM);
return -1;
} else if (d->u.function.variadic) {
- cdecl__err(CDECL_EVOIDPARAM, _("variadic function cannot have void parameter"));
+ cdecl__errmsg(CDECL__EVOIDPARAM);
return -1;
}
}
switch (d->type) {
case CDECL_DECL_FUNCTION:
- cdecl__err(CDECL_EBADRETURN, _("functions cannot return functions"));
+ cdecl__errmsg(CDECL__ERETFUNC);
return -1;
case CDECL_DECL_ARRAY:
- cdecl__err(CDECL_EBADRETURN, _("functions cannot return arrays"));
+ cdecl__errmsg(CDECL__ERETARRAY);
return -1;
}
switch (d->type) {
case CDECL_DECL_FUNCTION:
- cdecl__err(CDECL_EBADARRAY, _("array members cannot be functions"));
+ cdecl__errmsg(CDECL__EFUNCARRAY);
return -1;
}
for (spec = ptr->qualifiers; spec; spec = spec->next) {
if (spec->type == CDECL_QUAL_RESTRICT
&& d->type == CDECL_DECL_FUNCTION) {
- cdecl__err(CDECL_EBADPOINTER, _("function pointers cannot be restrict-qualified"));
+ cdecl__errmsg(CDECL__ERESTRICTFUNC);
return -1;
}
}
if (cdecl_is_abstract(i->declarators)
&& (i != decl || i->next)) {
- cdecl__err(CDECL_EBADDECL, _("mixing type names and declarations is not allowed"));
+ cdecl__errmsg(CDECL__EDECLTYPE);
goto err;
}
}
%code top {
/*
* Parser for C declarations.
- * Copyright © 2011-2012, 2021 Nick Bowler
+ * Copyright © 2011-2012, 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
#include "scan.h"
#include "cdecl.h"
#include "cdecl-internal.h"
+#include "errmsg.h"
#define FAIL(msg) do { \
yyerror(&yylloc, NULL, NULL, msg); \
#define ALLOC(ptr, size) do { \
(ptr) = malloc(size); \
if (!(ptr)) { \
- cdecl__err(CDECL_ENOMEM); \
+ cdecl__errmsg(CDECL__ENOMEM); \
YYERROR; \
} \
} while (0)
#include <ctype.h>
#include "cdecl-internal.h"
#include "cdecl.h"
+#include "errmsg.h"
#if HAVE_STRTOUMAX
/* Best case, implementation provides strtoumax. */
#define STRTOUMAX strtoul
#endif
-#define lex_error(...) do { \
- cdecl__err(CDECL_ENOPARSE, __VA_ARGS__); \
- return T_LEX_ERROR; \
-} while(0)
-
#define dup_token() do { \
yylval->strval = malloc(yyleng+1); \
if (!yylval->strval) { \
- cdecl__err(CDECL_ENOMEM); \
+ cdecl__errmsg(CDECL__ENOMEM); \
return T_LEX_ERROR; \
} \
strcpy(yylval->strval, yytext); \
errno = 0;
yylval->uintval = STRTOUMAX(yytext, &end, 0);
- if (errno == ERANGE)
- lex_error(_("integer constant out of range"));
- if (*end)
- lex_error(_("invalid integer constant"));
+ if (errno == ERANGE) {
+ cdecl__errmsg(CDECL__ERANGE);
+ return T_LEX_ERROR;
+ }
+ if (*end) {
+ cdecl__errmsg(CDECL__EBADINT);
+ return T_LEX_ERROR;
+ }
return T_UINT;
}
}
}
- lex_error(_("syntax error, unexpected '%s'"), buf);
+ cdecl__err(CDECL_ENOPARSE, _("syntax error, unexpected '%s'"), buf);
+ return T_LEX_ERROR;
}
#include "cdecl-internal.h"
#include "cdecl.h"
+#include "errmsg.h"
#include "tap.h"
#if ENABLE_NLS
const char expmsg[] = "failed to allocate memory";
const struct cdecl_error *err;
- tap_diag("cdecl__err(CDECL_ENOMEM)");
- cdecl__err(CDECL_ENOMEM);
+ tap_diag("cdecl__errmsg(CDECL__ENOMEM)");
+ cdecl__errmsg(CDECL__ENOMEM);
err = cdecl_get_error();
if (!tap_result(err->code == CDECL_ENOMEM, "returned error code")) {