/*
* Internal declarations for libcdecl.
- * Copyright © 2021, 2023 Nick Bowler
+ * Copyright © 2021, 2023-2024 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
-void cdecl__err(unsigned code, const char *fmt, const char *arg);
+void cdecl__err(const char *fmt, const char *arg);
void cdecl__errmsg(unsigned msg);
struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs);
struct parse_item *cdecl__alloc_item(size_t s_sz);
+/*
+ * GCC enables -finline-small-functions in most optimization modes; this works
+ * on a highlevel estimate of how big a function actually is and occasionally
+ * this produces really bad results.
+ *
+ * While old versions of GCC do not support this attribute the result seems
+ * to be merely a warning so hopefully we can get away with this check and
+ * save a configure test.
+ */
+#ifndef CDECL__NOINLINE
+# if __GNUC__
+# define CDECL__NOINLINE __attribute__((__noinline__))
+# else
+# define CDECL__NOINLINE /**/
+# endif
+#endif
+
#endif
/*
* Error handling for libcdecl.
- * Copyright © 2011-2012, 2021, 2023 Nick Bowler
+ * Copyright © 2011-2012, 2021, 2023-2024 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
* Sets the library error to code; fmt is a printf-style string that may use
* up to one %s directive, to refer to arg.
*/
-void cdecl__err(unsigned code, const char *fmt, const char *arg)
+void cdecl__err(const char *fmt, const char *arg)
{
struct err_state *state;
unsigned try = 0;
goto retry;
}
+ state->err.code = CDECL_ENOPARSE;
state->err.str = state->str;
- state->err.code = code;
}
const struct cdecl_error *cdecl_get_error(void)
%code top {
/*
* Parser for C declarations.
- * Copyright © 2011-2012, 2021, 2023 Nick Bowler
+ * Copyright © 2011-2012, 2021, 2023-2024 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
return yytname[YYTRANSLATE(token)];
}
-static void
+/*
+ * Current versions of GCC (up to 13) want to inline this function into the
+ * parser even when optimizing for size and the results are not great, so
+ * try to prevent such inlining.
+ */
+CDECL__NOINLINE static void
yyerror(YYLTYPE *loc, yyscan_t scanner, struct cdecl **out, const char *err)
{
if (strstr(err, yytname[YYTRANSLATE(T_LEX_ERROR)]))
return;
- cdecl__err(CDECL_ENOPARSE, "%s", err);
+ cdecl__err("%s", err);
}
c = yytext;
invalid_char:
to_readable_ch(buf, *c);
- cdecl__err(CDECL_ENOPARSE, _("syntax error, unexpected %s"), buf);
+ cdecl__err(_("syntax error, unexpected %s"), buf);
return T_LEX_ERROR;
}
/*
* Helper application to test internal library error reporting.
- * Copyright © 2023 Nick Bowler
+ * Copyright © 2023-2024 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
memset(work2, 'X', len - 1);
tap_diag("cdecl__err w/ %lu-byte string", (unsigned long)len);
- cdecl__err(1234, work1, "XX");
+ cdecl__err(work1, "XX");
memset(work1, 0, len);
err = cdecl_get_error();
- check_code(err, 1234);
+ check_code(err, CDECL_ENOPARSE);
errlen = strlen(err->str);
if (!tap_result(errlen == len-1, "returned string length")) {
abort();
sprintf(work, fmt, arg);
- cdecl__err(5432, fmt, arg);
+ cdecl__err(fmt, arg);
err = cdecl_get_error();
tap_diag("cdecl__err(\"%s\", \"%s\")", fmt, arg);
- check_code(err, 5432);
+ check_code(err, CDECL_ENOPARSE);
if (!tap_result(!strcmp(err->str, work), "returned string")) {
tap_diag("Failed, unexpected result");
{
}
-void cdecl__err(unsigned code, const char *fmt, const char *arg)
+void cdecl__err(const char *fmt, const char *arg)
{
}