]> git.draconx.ca Git - cdecl99.git/log
cdecl99.git
4 months agoBump dxcommon to pull in testsuite fixes.
Nick Bowler [Sat, 23 Dec 2023 21:55:11 +0000 (16:55 -0500)]
Bump dxcommon to pull in testsuite fixes.

4 months agolibcdecl: Prefer __inline in public header with GCC.
Nick Bowler [Thu, 21 Dec 2023 16:02:51 +0000 (11:02 -0500)]
libcdecl: Prefer __inline in public header with GCC.

If the library is built using GCC with default options, the configure
tests for inline will determine it is supported, and the installed
headers will use it.

But that doesn't mean the user is running the compiler in the exactly
the same mode when including the headers.  If they then use GCC in
strict C89 mode, "inline" is not recognized as a keyword and compilation
will fail.  We can avoid this problem by just always using __inline on
GCC, with a fallback to the configure-detected result.

4 months agocdecl99: Combine some printing calls.
Nick Bowler [Tue, 19 Dec 2023 13:31:23 +0000 (08:31 -0500)]
cdecl99: Combine some printing calls.

Replace some occurrences of multiple consecutive calls to printing
functions with a single equivalent printf, in cases where doing so
reduces the size of gcc output.

4 months agotests: Avoid use of AT_TESTED.
Nick Bowler [Tue, 19 Dec 2023 13:22:08 +0000 (08:22 -0500)]
tests: Avoid use of AT_TESTED.

This macro doesn't seem to handle systems with non-empty EXEEXT
properly.  All it does is prevent the testsuite from working.
We don't need such gratuitous failures, just log the output of
cdecl99 --version at the start of the test run and move on.

5 months agocdecl99: Optimize print_version a bit.
Nick Bowler [Wed, 13 Dec 2023 03:01:31 +0000 (22:01 -0500)]
cdecl99: Optimize print_version a bit.

Instead of a whole bunch of separate print calls, convert print_version
to a single call to a printing function, with a single string argument.
Compilers do not seem to coalesce multiple consecutive prints together,
so doing it explicitly gives a modest reduction in code size.

Wrap that all up into a new set of macros so that the same trick can
also be shared with the test applications.

5 months agocdecl99: Better "help" output on some old systems.
Nick Bowler [Thu, 7 Dec 2023 02:35:26 +0000 (21:35 -0500)]
cdecl99: Better "help" output on some old systems.

Some very old printf implementations return 0 on success instead of the
number of bytes written.  We should never see a return of 0 normally,
so we can improve the output to be less of a garbled mess by printing
a newline if that happens (same as the error case).  This is a simple
tweak that should have virtually no impact on modern systems.

5 months agocdecl99: Fix "help" command on ULTRIX.
Nick Bowler [Thu, 7 Dec 2023 02:12:04 +0000 (21:12 -0500)]
cdecl99: Fix "help" command on ULTRIX.

ULTRIX 4.5 nawk does not always interpret a nonempty string as "true",
so install a workaround to the gen-cmdlist.awk script for this issue.

And fix the test suite which purports to test this command but failed
to notice that no useful help was printed.

5 months agotests: Try not to split fields in randomdecl sanity test.
Nick Bowler [Wed, 6 Dec 2023 06:17:56 +0000 (01:17 -0500)]
tests: Try not to split fields in randomdecl sanity test.

HP-UX 11 awk will simply exit with an error if any input line has more
than 199 fields.  To avoid this happening in the randomdecl sanity test,
set FS to some garbage because we don't actually use any of the field
variables in this script.

5 months agoExplicitly require gnulib stdbool module.
Nick Bowler [Wed, 6 Dec 2023 05:33:06 +0000 (00:33 -0500)]
Explicitly require gnulib stdbool module.

It seems that updating gnulib has caused this to not always be pulled
in, in particular the header is no longer generated on HP-UX 11, leading
to build failures.

5 months agoWork around some ULTRIX make bugs.
Nick Bowler [Wed, 6 Dec 2023 04:05:17 +0000 (23:05 -0500)]
Work around some ULTRIX make bugs.

ULTRIX 4.5 make fails during rule lookup when it tries to build a
target in a nonexistent directory that might have inference rules
associated with it (i.e., ends with a defined suffix), for example:

  % echo 'nonexistent/baz.o: ;' | make -f -
  Directory nonexistent/: Make: Cannot open.  Stop.

We can work around this problem by using a prerequisite to create the
output directory instead of trying to create it directly in the rule.
Automake actually does this already for its own rules, so let's try
to hook the same mechanism.

Pull in similar fixes from dxcommon.

5 months agoSkip Bison api.token.raw probe if Bison is not found.
Nick Bowler [Wed, 6 Dec 2023 01:34:20 +0000 (20:34 -0500)]
Skip Bison api.token.raw probe if Bison is not found.

Printing the api.token.raw probe when Bison was not found at all gives
strange configure output, let's just make the whole check conditional.

5 months agoBump dxcommon to get help output improvements.
Nick Bowler [Tue, 5 Dec 2023 05:49:34 +0000 (00:49 -0500)]
Bump dxcommon to get help output improvements.

As well as a nice size reduction on modern platforms, basically
everything is working on ULTRIX 4.5 now too, cool.

5 months agotests: Avoid using awk -v option.
Nick Bowler [Tue, 5 Dec 2023 05:37:35 +0000 (00:37 -0500)]
tests: Avoid using awk -v option.

Traditional awk implementations do not support -v, and this is also
the case with ULTRIX 4.5 nawk.  The tests that use -v don't actually
need to use it, so it doesn't hurt to fix this.

5 months agotests: Work around some ancient printf bugs.
Nick Bowler [Tue, 5 Dec 2023 05:34:27 +0000 (00:34 -0500)]
tests: Work around some ancient printf bugs.

Some very old printf implementations (e.g., on ULTRIX 4.5) do not
support negative precision with %.*s conversions in order to behave
as if the precision was omitted.

It is easy to change the rendertest program to avoid this problem,
so let's change it.

5 months agotests: Better output filter in randomdecl sanity test.
Nick Bowler [Mon, 4 Dec 2023 05:14:47 +0000 (00:14 -0500)]
tests: Better output filter in randomdecl sanity test.

Instead of a big sed program producing thousands of lines to then
extract the unique ones, use an awk program that follows the same
basic concept but only prints any particular line once.

5 months agoUse awk over printf when generating atlocal.
Nick Bowler [Mon, 4 Dec 2023 03:57:38 +0000 (22:57 -0500)]
Use awk over printf when generating atlocal.

We use awk extensively already and it will do the job here.  SVr4
printf does not implement the POSIX behaviour of repeating the output
when there are more arguments than needed for the given format string.

5 months agoFix tests build on compilers without _Bool.
Nick Bowler [Mon, 4 Dec 2023 02:17:46 +0000 (21:17 -0500)]
Fix tests build on compilers without _Bool.

For these test programs, there is no advantage to using _Bool over
just plain "int" or whatever.

5 months agoFix parser build on compilers without _Bool.
Nick Bowler [Sun, 3 Dec 2023 20:14:38 +0000 (15:14 -0500)]
Fix parser build on compilers without _Bool.

Although we have a perfectly fine replacement for compilers that do
not implement _Bool, we have to have #include <stdbool.h> in order
to get it, which was missing from the parser header.

5 months agolibcdecl: Add _Bool fallback to public header.
Nick Bowler [Sun, 3 Dec 2023 22:31:26 +0000 (17:31 -0500)]
libcdecl: Add _Bool fallback to public header.

Even though we have a fallback for _Bool when building the library,
it is missing in some source files that include cdecl.h.  But more
importantly, it is not available to downstream users of the installed
header file.

As far as I'm aware, all compilers which support _Bool in any mode also
support it in strict C89 mode, so it should be sufficient to just use
_Bool if configure detected support for it.  We integrate the newfangled
bake-config script so that the installed header embeds this config.

There is also one inline function which returns _Bool.  We can just
change it to return int instead, since there is no ABI implication.

5 months agoDon't build locale/wcwidth junk if NLS is disabled.
Nick Bowler [Sun, 3 Dec 2023 21:54:07 +0000 (16:54 -0500)]
Don't build locale/wcwidth junk if NLS is disabled.

These functions are only used for NLS support, so it is silly to
compile them if NLS is disabled for any reason.

To do this, we create a local "dx-nls" gnulib module which can in
turn use conditional dependencies to pull in all the (now optional)
modules.

It is necessary to update gnulib in order for this to actually work,
as otherwise uniwidth/width is still compiled for some reason, and
it looks like this has been fixed upstream.

5 months agoMigrate gnulib patches to new common helper macro.
Nick Bowler [Fri, 1 Dec 2023 03:46:58 +0000 (22:46 -0500)]
Migrate gnulib patches to new common helper macro.

Using the new DX_PATCH_GNULIB macro allows m4 to implement the patches
that were previously being done in bootstrap, as well as removing the
repeated runtime test to work around the solaris underquoting problem
in threadlib.m4.

This also changes MinGW builds to use native Windows threads by default.

5 months agoAvoid the use of for loop declarations.
Nick Bowler [Thu, 30 Nov 2023 01:56:44 +0000 (20:56 -0500)]
Avoid the use of for loop declarations.

This C99 syntax is now almost entirely contained to test programs;
at this point using such syntax is just an obstacle to a successful
build rather than anything useful.

It is now possible to build with gcc in C89 mode, and probably some
other pre-C99 compilers.

One annoyance is the reference code for the RNG uses such declarations.
We avoid changing the reference code and instead arrange for the test
to be skipped unless compiler support is available.

5 months agotests: Use TAP helpers in rng-test.
Nick Bowler [Thu, 30 Nov 2023 01:42:07 +0000 (20:42 -0500)]
tests: Use TAP helpers in rng-test.

I imagine the helpers were avoided originally to avoid extra files in
the distribution, but they're there anyway now so there seems to be
no reason not to use them.

5 months agoBump dxcommon to fix "make install" with old shells.
Nick Bowler [Wed, 22 Nov 2023 04:49:04 +0000 (23:49 -0500)]
Bump dxcommon to fix "make install" with old shells.

The translation installation rules were busted on HP-UX /bin/sh,
heirloom-sh, probably old Solaris and maybe others.

5 months agoAdd a basic "make installcheck" function.
Nick Bowler [Wed, 22 Nov 2023 01:25:04 +0000 (20:25 -0500)]
Add a basic "make installcheck" function.

Add a very simple post-install test which simply attempts to compile,
link and run a test program against the installed header and library.

5 months agoTrivial manual fixes.
Nick Bowler [Sun, 19 Nov 2023 04:01:41 +0000 (23:01 -0500)]
Trivial manual fixes.

For literal strings, we need to use \- instead of just - as some troff
processors turn plain "-" into "proper" unicode hyphens (as opposed to
hyphen-minus), which breaks copy+paste and searching.

Ensure that .Os follows .Dt in the mdoc prologue as apparently not doing
this results in broken manpage headings with groff 1.23.

5 months agolibcdecl: Prefer memchr over strchr in the scanner.
Nick Bowler [Sun, 19 Nov 2023 01:05:23 +0000 (20:05 -0500)]
libcdecl: Prefer memchr over strchr in the scanner.

Since nothing else in the library uses strchr, but we do use memchr
elsewhere, using memchr instead avoids a comparatively expensive PLT
entry.  We already know the string length so the only real difference
is the additional argument marshalling.

5 months agolibcdecl: Fully remove snprintf requirement from the library.
Nick Bowler [Sat, 18 Nov 2023 21:41:44 +0000 (16:41 -0500)]
libcdecl: Fully remove snprintf requirement from the library.

There is only one remaining unconditional snprintf usage in the library,
which implements the cdecl__strlcpy function.  Replacing this with an
alternate implementation means we no longer need snprintf at all except
when NLS is enabled (in that case, we assume snprintf is available --
possibly provided by GNU libintl).

So we can drop quite a lot of gnulib code potentially going into the
library.  The usual gnulib behaviour is to substitute complete re-
implementations for almost any possible problem, even ones that are
totally irrelevant to the usage at hand.

Bumping dxcommon removes snprintf from the applications too so we can
drop all of this nonsense.  On systems that used the snprintf fallback,
this reduces the overall library size by about 30%.

5 months agolibcdecl: reduce snprintf reliance for error reporting.
Nick Bowler [Wed, 15 Nov 2023 03:43:00 +0000 (22:43 -0500)]
libcdecl: reduce snprintf reliance for error reporting.

Add a fallback formatting method using the main libcdecl rendering
functions which works in the NLS-disabled case.

We don't need to avoid snprintf if NLS is enabled, as GNU libintl
will provide a usable snprintf if the system does not.

6 months agolibcdecl: Simplify loop in cdecl__normalize_specs.
Nick Bowler [Thu, 26 Oct 2023 01:28:17 +0000 (21:28 -0400)]
libcdecl: Simplify loop in cdecl__normalize_specs.

Restructure the code a bit to make this loop a bit more straightforward.

6 months agolibcdecl: Avoid snprintf for integer conversions.
Nick Bowler [Thu, 26 Oct 2023 00:59:16 +0000 (20:59 -0400)]
libcdecl: Avoid snprintf for integer conversions.

To reduce the library dependency on gnulib replacements, implement the
conversion of uintmax_t to decimal by simple repeated division.  This
way avoids any need to worry about whether the C library can actually
perform 64-bit decimal conversions properly.

6 months agotests: Add sanity check for truncated output.
Nick Bowler [Wed, 25 Oct 2023 01:21:49 +0000 (21:21 -0400)]
tests: Add sanity check for truncated output.

Nothing really verifies that output truncation of the cdecl_declare
and cdecl_explain functions actually works as expected.

Add a new test program and a couple invocations to at least cover
the basic functionality.

9 months agoExpand some sections of the libcdecl manual.
Nick Bowler [Fri, 28 Jul 2023 06:04:52 +0000 (02:04 -0400)]
Expand some sections of the libcdecl manual.

- Clarify that the memory management details wrt. cdecl_parse_decl and
  cdecl_parse_english are unspecified.

- Add more detail to the description of cdecl_explain and cdecl_declare.

- Clarify that it is allowed to pass a 'struct cdecl' with a NULL
  specifiers list to cdecl_declare.

9 months agocdecl99: Combine all the main command implementations.
Nick Bowler [Fri, 28 Jul 2023 06:01:53 +0000 (02:01 -0400)]
cdecl99: Combine all the main command implementations.

The explain, simplify and declare (or type) commands are all virtually
identical.  The primary difference is just which parser mode to use,
and which output mode to use, with the various combinations giving
the various commands.

Other than some very slight tweak to the formatting to handle "simplify"
with multiple full declarators, we can just implement one function that
does all three operations: a pretty nice cleanup.

9 months agolibcdecl: Fix output regression with multiple declarators.
Nick Bowler [Fri, 28 Jul 2023 04:22:11 +0000 (00:22 -0400)]
libcdecl: Fix output regression with multiple declarators.

It turns out that the cdecl99 program implemented the simplify command
using the undocumented behaviour of calling cdecl_declare with NULL
specifiers to output just the declarator part.

Recent changes to the library partially broke that usage by printing an
extra space in this case.  This went unnoticed as the simplify command
is only lightly tested and nothing checks its behaviour with multiple
declarators.

Fortunately it is very easy to restore the old behaviour in the library,
and to add a test case to verify this behaviour.

9 months agolibcdecl: Work around GNU libc snprintf bug.
Nick Bowler [Fri, 28 Jul 2023 04:00:12 +0000 (00:00 -0400)]
libcdecl: Work around GNU libc snprintf bug.

Apparently, with GNU libc (even contemporary versions), you cannot simply
pass an arbitrarily-large length.  It appears that glibc internally adds
the provided length to the provided destination pointer, and if that
calculation overflows, then the actual output is silently truncated.

I believe this to be an error in glibc; the only thing the specification
for snprintf says about the length n is that output characters beyond
the "n-1st" are discarded, which doesn't imply that it is invalid to
for a program to pass large length values.  But it doesn't really
matter, we just have to deal with this behaviour since it exists.

This only affects the parser syntax error path, since 41ff7ec97691
("libcdecl: Simplify Bison error message reporting.") changed that to
use cdecl__strlcpy with a large size (INT_MAX).  The normal output path
always passes an actual buffer length.  The bison-generated syntax error
code does not track buffer lengths, but it does ensure the buffer is
large enough so we can use strlen to infer a suitable length.

A new test case is added to sortof directly test the issue, without
the fix it reliably fails for me on 32-bit x86, as the stack above 2G.
The invalid character test also fails because of this issue, but for a
subtly different reason.

9 months agolibcdecl: Perform all parser allocations via cdecl__alloc_item.
Nick Bowler [Tue, 25 Jul 2023 00:56:56 +0000 (20:56 -0400)]
libcdecl: Perform all parser allocations via cdecl__alloc_item.

The cdecl__alloc_item function internally does some basic initialization
and handles error reporting, so by using it consistently we can avoid
some of this stuff being repeated throughout the parser actions, which
gives a slight reduction in the size of the parser.

As this function allocates a fixed-sized union of all the parse tree
structures, this means a small amount of runtime memory may be wasted
for the smaller ones, but it should be less than 12 bytes per allocation.

9 months agolibcdecl: Replace ALLOC_STRUCT with specialized macros.
Nick Bowler [Mon, 24 Jul 2023 23:57:56 +0000 (19:57 -0400)]
libcdecl: Replace ALLOC_STRUCT with specialized macros.

While there is some appeal to this generic "do everything" macro,
it depends on a bunch of modern C syntax (variadic macros, compound
literals, designated initializers) which is not always correctly
implemented.  We've already had to work around at least one compiler
bug in the code directly related to this macro.

Using specialized macros for each kind of allocation works better
on older implementations, and moreover we seem to get more compact
code out of modern ones too, probably because compound literals
initialize all members and we don't always need that.

9 months agolibcdecl: Factor out toplevel parser actions.
Nick Bowler [Mon, 24 Jul 2023 04:10:22 +0000 (00:10 -0400)]
libcdecl: Factor out toplevel parser actions.

Using a separate rule so there is just one semantic action for the
start symbol seems to give a slight code size improvement.

9 months agolibcdecl: Fix memory leak when parsing e.g., int () int.
Nick Bowler [Mon, 24 Jul 2023 03:46:36 +0000 (23:46 -0400)]
libcdecl: Fix memory leak when parsing e.g., int () int.

After the parser reduces the start symbol, it can still fail if the
scanner returns additional tokens.  In this case, nobody frees the
parse tree that was already output by the previously-executed parser
actions.

Solve this by simply freeing the output tree in the caller on error.

We make a slight adjustment to the "interactive" test case so that it
will tickle this particular issue.  When using "leak sanitizer", the
leak will be found and a nonzero exit status will be substituted,
failing the test.

The existing "command error messages" test also notices the problem when
using "leak sanitizer", but not because of the exit status: it only sees
text printed to stderr in the wrong format.

9 months agolibcdecl: Don't dynamically allocate null declarators.
Nick Bowler [Sun, 23 Jul 2023 19:37:32 +0000 (15:37 -0400)]
libcdecl: Don't dynamically allocate null declarators.

Since identifiers now come with their own declarator allocations,
nothing actually modifies any part of an allocated null declarator.

And since null declarators are always the same (with all members zero),
we don't even need to allocate them at all.  Just use a single static
allocation and make every reference to a null declarator point to that.

Then we just need to not free null declarators in the various places
where that currently happens.

9 months agolibcdecl: Combine identifier and struct allocation.
Nick Bowler [Sun, 23 Jul 2023 19:06:29 +0000 (15:06 -0400)]
libcdecl: Combine identifier and struct allocation.

Whenever the parser uses an identifier token, it is always to stuff
it into a newly-allocated declarator or declspec structure.

So we can reduce the amount of work that needs to be done in the
parser actions by by pre-allocating a declarator structure in the
scanner.  By using a union, we can also use this same allocation
for the declspec case.

And by happy accident, some of the structure members are identical
between both cases, and GCC at least recognizes that it doesn't need
to do anything to copy e.g., declarator.u.ident to declspec.ident
within the union.

9 months agoFree working memory in crossparse test.
Nick Bowler [Sun, 23 Jul 2023 17:15:16 +0000 (13:15 -0400)]
Free working memory in crossparse test.

When reading from a file, the getline buffer is not explicitly freed by
the test application, which shows up as leaked memory in memory debugging
tools.  Let's fix that so we don't mistake that for an actual leak in
the library.

9 months agocdecl99: Remove some unused variable declarations.
Nick Bowler [Sun, 23 Jul 2023 16:47:55 +0000 (12:47 -0400)]
cdecl99: Remove some unused variable declarations.

9 months agoAvoid warnings about unused scanner functions.
Nick Bowler [Sun, 23 Jul 2023 15:48:33 +0000 (11:48 -0400)]
Avoid warnings about unused scanner functions.

We don't use input or unput in the scanner, so we can define some
macros to disable them which avoids some compiler warnings.

9 months agoSolve Bison conflicts using precedence declarations.
Nick Bowler [Sun, 23 Jul 2023 14:55:40 +0000 (10:55 -0400)]
Solve Bison conflicts using precedence declarations.

We can use a precedence declaration to directly inform Bison of how
to resolve the specific conflict at hand, rather than just saying
"it is ok to have N conflicts."

There is no significant change to the generated output but this way
keeps things more straightforward when modifying the parser.

9 months agotests: Add sanity test for variable-length arrays.
Nick Bowler [Fri, 21 Jul 2023 03:55:46 +0000 (23:55 -0400)]
tests: Add sanity test for variable-length arrays.

The random crossparse test generates these quite frequently but
it's nice to have the basics covered by simpler inputs.

9 months agolibcdecl: Remove magic T_ENGLISH token.
Nick Bowler [Fri, 21 Jul 2023 03:23:00 +0000 (23:23 -0400)]
libcdecl: Remove magic T_ENGLISH token.

This token is pointless, all english syntax is already sufficiently
distinguished by the T_DECLARE and T_TYPE tokens, which are only
returned by the scanner in english mode.

9 months agolibcdecl: Simplify Bison error message reporting.
Nick Bowler [Thu, 20 Jul 2023 02:22:10 +0000 (22:22 -0400)]
libcdecl: Simplify Bison error message reporting.

Bison emits a bunch of code to pretty print token names for error
messages, doing things like removing quotes and backslashes.

But this is all totally pointless: all of the relevant strings are
already correctly formatted (in part because fix-yytname.awk does
some of this at compile time), and the process will not alter them.
They simply need to be copied as-is.

Fortunately, Bison provides a simple mechanism to replace this with
our own function, and wouldn't you know it we already have a suitable
copying function in the library, so let's use that.

9 months agolibcdecl: Sidestep some possible snprintf issues.
Nick Bowler [Thu, 20 Jul 2023 02:12:24 +0000 (22:12 -0400)]
libcdecl: Sidestep some possible snprintf issues.

Adjust cdecl__emit to avoid some known problems with snprintf
implementations:

 * some implementations (e.g., newlib 1.8.2) write to the destination
   when the size is zero.
 * some implementations (e.g., HP-UX 11) return -1 when the string is
   truncated.
 * some implementations (e.g., the replacement provided by gnulib!)
   allocate memory even for trivial conversions and return -1 on malloc
   failure.

Since we currently use gnulib, only the last one is presently a concern,
but the plan is to eventually remove the library dependency on gnulib
snprintf since in reality we barely need any snprintf functionality.

Adjust the cdecl__emit implementation to simply avoid tripping over these
sorts of problems.  Other snprintf calls in the library remain as before.

9 months agolibcdecl: Combine tag/typedef identifier rules.
Nick Bowler [Thu, 20 Jul 2023 01:25:09 +0000 (21:25 -0400)]
libcdecl: Combine tag/typedef identifier rules.

There are actually no conflicts to add an empty production alongside
the rule for "struct", "union" and "enum", which allows the subsequent
reductions for "tag identifier" and "[nothing] identifier" to be done
with just one rule.

This replaces a relatively large action from the eliminated rule with
a very simple one.

9 months agolibcdecl: Avoid using strcpy w/ empty strings.
Nick Bowler [Thu, 20 Jul 2023 01:15:14 +0000 (21:15 -0400)]
libcdecl: Avoid using strcpy w/ empty strings.

The parser is currently using strcpy to copy constant empty strings; it
is just as easy to explicitly assign the single zero byte instead.

Since these are the only use of strcpy in the library, and for whatever
reason GCC is not optimizing out these strcpy calls, on ELF hosts this
saves a PLT entry in the shared library and everything associated with
that too.

9 months agolibcdecl: Combine array length parser rules.
Nick Bowler [Thu, 20 Jul 2023 01:08:03 +0000 (21:08 -0400)]
libcdecl: Combine array length parser rules.

Some of the parser rules to handle incomplete array types versus arrays
with explicit length (not VLAs) are duplicated between the regular and
english parsers.

As this is the same in both cases we can use a new symbol and drop some
duplicate actions to simplify things a bit.

9 months agolibcdecl: Parse function parameters in order.
Nick Bowler [Thu, 20 Jul 2023 00:52:21 +0000 (20:52 -0400)]
libcdecl: Parse function parameters in order.

Currently the parser collects function parameters in reverse order,
then reverses them at the end.

There is no reason to do this.  It is only a slight restructuring of
the rules to collect parameters in the right order from the get go,
which means we can delete the duplicated list reversal code.

The grammar itself is also simpler this way, using two less nonterminals.

9 months agolibcdecl: Factor out open-coded identifier patchup.
Nick Bowler [Thu, 20 Jul 2023 00:40:32 +0000 (20:40 -0400)]
libcdecl: Factor out open-coded identifier patchup.

There are two parser rules which handle english declarations of the
form "identifier as type", these have to traverse the type name
to replace the "null" declarator with the identifier.

Instead of duplicating the code for this traversal, let's use a
helper function to do it.

9 months agolibcdecl: Factor out open-coded list concatenation.
Nick Bowler [Thu, 20 Jul 2023 00:28:59 +0000 (20:28 -0400)]
libcdecl: Factor out open-coded list concatenation.

The parser has two rules which join two lists.  Let's add a helper
to do that instead of duplicating the code for list concatenation.
Furthermore, in both cases one of the lists is known to be nonempty;
the implementation can be slightly simplified with that assumption.

9 months agolibcdecl: Fix crash when bootstrapped w/ old Bison.
Nick Bowler [Thu, 20 Jul 2023 00:22:32 +0000 (20:22 -0400)]
libcdecl: Fix crash when bootstrapped w/ old Bison.

We are comparing the packed token value to check whether this is an
identifier or a keyword against the true value.  This happens to work
on new Bison (when using api.token.raw) as these values are the same,
but on old Bison the result is never true.

Thus, the scanner fails to assign the "strval" for identifier tokens
and the result fails very badly.  Easy enough to fix.

9 months agolibcdecl: Avoid redundant string literal in yyerror.
Nick Bowler [Tue, 18 Jul 2023 02:33:03 +0000 (22:33 -0400)]
libcdecl: Avoid redundant string literal in yyerror.

The T_LEX_ERROR string literal in yyerror won't be merged with the
now-duplicate string in the token name table; use the appropriate
indirection to shave off some bytes.

9 months agolibcdecl: Don't propagate specifier lists more than once.
Nick Bowler [Tue, 18 Jul 2023 02:20:07 +0000 (22:20 -0400)]
libcdecl: Don't propagate specifier lists more than once.

The very first thing the library does with the parse tree is normalize
the top-level specifiers, and then propagate the resulting list across
all top-level declarators.

So it is completely redundant for the parser itself to propagate the
un-normalized specifier list.

9 months agoAdd an explanation for declaration specifier rules.
Nick Bowler [Tue, 18 Jul 2023 01:55:28 +0000 (21:55 -0400)]
Add an explanation for declaration specifier rules.

It took me a while to wrap my head around WTF the declaration specifier
parser rules were trying to accomplish.  Let's add a big explanation so
hopefully, if I try to read them again after another decade or so, they
will make sense more easily.

10 months agolibcdecl: Move specifier type determination into scanner.
Nick Bowler [Fri, 14 Jul 2023 01:25:04 +0000 (21:25 -0400)]
libcdecl: Move specifier type determination into scanner.

Instead of having a parser action for every keyword which sets the
appropriate specifier type, the scanner can just directly assign
the semantic value for the returned specifier tokens.

This reduces the size of the generated parser quite a bit, without
needing any change to the tokens.

10 months agolibcdecl: Use macros for packing tokens into bytes.
Nick Bowler [Fri, 14 Jul 2023 01:20:26 +0000 (21:20 -0400)]
libcdecl: Use macros for packing tokens into bytes.

Instead of coding the same structures everywhere, move the logic to
drop/restore the upper bits of tokens into helper macros.

Should be no functional change.

10 months agoUpdate .gitmodules URI for Gnulib.
Nick Bowler [Fri, 14 Jul 2023 00:42:37 +0000 (20:42 -0400)]
Update .gitmodules URI for Gnulib.

Apparently the https://git.savannah.gnu.org/r/gnulib.git location
doesn't support the smart protocol over HTTP, but /git/gnulib.git
does.  Weird.

10 months agolibcdecl: Avoid duplicating keyword strings w/ gperf.
Nick Bowler [Tue, 11 Jul 2023 04:57:04 +0000 (00:57 -0400)]
libcdecl: Avoid duplicating keyword strings w/ gperf.

The string table generated by gperf is quite redundant: since we already
resolved to the parser token, we can easily get the string from the
parser's token name table.

Unfortunately gperf provides no options to customize the string table
generation to the extent needed, so let's continue our theme of post-
processing everything in awk.

10 months agolibcdecl: Combine scanner rules for punctuation.
Nick Bowler [Sun, 9 Jul 2023 20:51:29 +0000 (16:51 -0400)]
libcdecl: Combine scanner rules for punctuation.

Use a single rule to match all punctuation, with a lookup table to
return the correct token.  This gives a small size reduction for
the scanner.

10 months agolibcdecl: Use gperf to identify keywords during scanning.
Nick Bowler [Sun, 9 Jul 2023 18:43:43 +0000 (14:43 -0400)]
libcdecl: Use gperf to identify keywords during scanning.

Instead of having a flex rule for each keyword, we can use a catch-all
rule for identifiers and then use gperf to distinguish keywords from
ordinary identifiers.

This reduces the size of the scanner much more than the addition of
gperf-generated code increases it.

10 months agotests: Fix interactive test without libreadline.
Nick Bowler [Sat, 8 Jul 2023 17:33:29 +0000 (13:33 -0400)]
tests: Fix interactive test without libreadline.

When using actual readline, the user's input is echoed internally, so
the test case sees the actual input commands in the captured standard
output.  But in the getline-based fallback, the input is not reflected
to the output.  This is expected behaviour, but confuses the test case.

Rewrite the check to accept either form.

10 months agolibcdecl: Use Bison's api.token.raw feature.
Nick Bowler [Sat, 8 Jul 2023 14:04:31 +0000 (10:04 -0400)]
libcdecl: Use Bison's api.token.raw feature.

By default, Bison numbers user-defined tokens starting from 257.
If the scanner never returns plain characters (which is the case
for libcdecl), this is inefficient.

Recent versions of Bison provide the api.token.raw option to improve
things.  Let's turn it on, if configure detects that it is supported.

This requires a very minor tweak to spec_string in order for the
encoding of tokens into single-byte values to work regardless of
which mode Bison is run in.

10 months agolibcdecl: Re-use strings from parser in spec_string.
Nick Bowler [Fri, 7 Jul 2023 03:56:29 +0000 (23:56 -0400)]
libcdecl: Re-use strings from parser in spec_string.

With the fixups applied by fix-yytname, we now have two distinct string
tables containing the same strings.  To avoid this duplication, add a
new internal function to allow spec_string to access the parser's token
name table.

10 months agolibcdecl: Replace yytname array in the Bison parser.
Nick Bowler [Fri, 7 Jul 2023 02:46:20 +0000 (22:46 -0400)]
libcdecl: Replace yytname array in the Bison parser.

Bison generates a list of symbol names as a static array of char pointers
initialized with string literals, which is simply horrible.  These pointers
are two to four times larger than necessary, but with position-independent
code this also forces them into an unshareable, writeable segment since
they are not compile-time constants and must be initialized by the dynamic
loader at runtime.

Furthermore, the names of nonterminal symbols are always included but they
are not always needed; they should only be output by tracing code which
is disabled by default at compile time.

Fix this by adding a new build script which postprocesses the output,
replacing the yytname array with a function implementing the same lookup
with truly constant tables.  Inclusion of nonterminals is now conditional
on YYDEBUG.

This is a big win, reducing the overall library size about 5 to 10 percent
(64-bit hosts see the most improvement).

10 months agotests: Ensure that English keywords can be parsed.
Nick Bowler [Fri, 7 Jul 2023 01:02:25 +0000 (21:02 -0400)]
tests: Ensure that English keywords can be parsed.

We don't want to reject words like "declare" in identifiers, at least
when parsing C code, so add test cases to make sure that works.

10 months agotests: Don't pull output routines into normalize testcase.
Nick Bowler [Fri, 7 Jul 2023 00:57:41 +0000 (20:57 -0400)]
tests: Don't pull output routines into normalize testcase.

This program isn't about testing the output routines, and it's simple
enough to just have the test program do its own printing, so linking
in the output routines to this testcase is just causing more trouble
than it's worth.

10 months agolibcdecl: Combine error and i18n init.
Nick Bowler [Fri, 7 Jul 2023 00:50:22 +0000 (20:50 -0400)]
libcdecl: Combine error and i18n init.

We can just do the gettext initialization at the same time as error
initialization, which lets us use a single "glthread_once" invocation
for everything.

10 months agolibcdecl: Fix regression in function parsing.
Nick Bowler [Thu, 6 Jul 2023 06:15:35 +0000 (02:15 -0400)]
libcdecl: Fix regression in function parsing.

Merging the reduce_parentheses and simplify_functions step missed a case
where the function simplification could pull a fake function declarator
up to the current tree position.  Continuing the tree traversal will miss
this, leaving the fake parameter in the tree (which is then rejected as
a syntax error later).

The fix is easy enough, just repeat the whole reduction step until no
changes are needed at the current position before continuing traversal.

Add a new test case that targets this behaviour.

10 months agolibcdecl: Remove "too many parentheses" error check.
Nick Bowler [Thu, 6 Jul 2023 05:59:43 +0000 (01:59 -0400)]
libcdecl: Remove "too many parentheses" error check.

It is simply not the case that "int ((int))" is invalid.

Since "int (x(int))" declares x as a function returning int, it follows
that "int ((int))" is simply a type name for function returning int.
Likewise, "int (((int)))" is equivalent, etc.

Rejecting these type names is longstanding broken behaviour.  I think
the entire error check can simply be deleted outright, along with its
associated error message.  The bogus negative test cases are replaced
with new positive tests.

Furthermore, rewrite the big comment that suggests this was reasonable
behaviour, replacing it with a (hopefully) better explanation that
covers how this particular case should be interpreted.

10 months agocdecl99: Simplify main loops a bit.
Nick Bowler [Wed, 5 Jul 2023 05:48:11 +0000 (01:48 -0400)]
cdecl99: Simplify main loops a bit.

Convert the calls to repl/repl_execute to tail calls from main.

10 months agocdecl99: Reverse sense of "interactive" global variable.
Nick Bowler [Wed, 5 Jul 2023 01:39:55 +0000 (21:39 -0400)]
cdecl99: Reverse sense of "interactive" global variable.

Instead of a default-true "interactive" global variable, we can use
a default-false "batch" global variable, reversing the sense of all
the tests.

This moves the variable from the initialized data segment into bss,
which is more efficient.

10 months agocdecl99: Don't check blank lines if no history support.
Nick Bowler [Wed, 5 Jul 2023 01:27:47 +0000 (21:27 -0400)]
cdecl99: Don't check blank lines if no history support.

Move the whole "if not blank, then add history" logic under the #ifdef,
so it can be eliminated completely if add_history is not available at
compile time.

This probably makes no major difference on GNU/Linux, since GCC knows
that strspn has no side effects and can drop the call as dead code, but
this may help with less sophisticated toolchains.

10 months agocdecl99: Fall back to getline, instead of Gnulib's readline.
Nick Bowler [Wed, 5 Jul 2023 01:15:39 +0000 (21:15 -0400)]
cdecl99: Fall back to getline, instead of Gnulib's readline.

When building without readline, instead of using Gnulib's readline
replacement, use getline directly.  We can combine most of the batch
and interactive mode processing loops which saves a bunch of pointless
extra code in the readline-disabled case.

To actually do this, we prepare a Gnulib "local dir" to implement
a cut-down readline module that includes the configure tests only.

10 months agoAdd test for interactive mode.
Nick Bowler [Wed, 5 Jul 2023 00:57:06 +0000 (20:57 -0400)]
Add test for interactive mode.

We currently don't have any tests which actually run cdecl99 in the
interactive mode.  Let's fix that, shall we?

10 months agolibcdecl: Simplify mixed type name error condition.
Nick Bowler [Sat, 1 Jul 2023 03:03:09 +0000 (23:03 -0400)]
libcdecl: Simplify mixed type name error condition.

"List item X is either not the first or not the last item" is just a
very complicated way to say "the list has more than one item".

10 months agotests: Add more coverage for parenthesis handling.
Nick Bowler [Sat, 1 Jul 2023 02:09:33 +0000 (22:09 -0400)]
tests: Add more coverage for parenthesis handling.

Add a couple extra test cases which cover some special behaviours
that are apparently missed by the existing tests.

10 months agolibcdecl: Simplify reduce_parentheses implementation.
Nick Bowler [Fri, 30 Jun 2023 05:24:12 +0000 (01:24 -0400)]
libcdecl: Simplify reduce_parentheses implementation.

Simplify the reduce_parentheses implementation so it operates in a
much more straightforward way.  We can also just call simplify_functions
directly during the same tree traversal, instead of trying to predict
what simplify_functions will do to a node on a later traversal.

10 months agolibcdecl: Combine several postprocessing steps into one.
Nick Bowler [Fri, 30 Jun 2023 01:22:44 +0000 (21:22 -0400)]
libcdecl: Combine several postprocessing steps into one.

We currently have 5 postprocessing steps common to both parse variants,
four of which don't do any modification at all (just syntax checks).
This is overkill.  We can easily combine all five of these operations
into one function which does everything in a single tree traversal.

10 months agolibcdecl: Simplify declarator traversal logic.
Nick Bowler [Wed, 28 Jun 2023 05:07:59 +0000 (01:07 -0400)]
libcdecl: Simplify declarator traversal logic.

It seems unnecessary to handle the case where the traversal function
modifies the subtree differently from the case where the function does
not modify the subtree.

So we only have to deal with two cases for the traversal function's
return value, which allows us to simplify a bit.

10 months agolibcdecl: Merge both parser function implementations.
Nick Bowler [Wed, 28 Jun 2023 02:48:11 +0000 (22:48 -0400)]
libcdecl: Merge both parser function implementations.

The only remaining meaningful difference between the cdecl_parse_decl
and cdecl_parse_english implementations is the function-simplification
passes are only done for cdecl_parse_decl.

We can easily just make those conditional in a common parser function,
to reduce code duplication.

10 months agolibcdecl: Simplify sorting in cdecl__normalize_specs.
Nick Bowler [Tue, 27 Jun 2023 02:08:01 +0000 (22:08 -0400)]
libcdecl: Simplify sorting in cdecl__normalize_specs.

Rewrite the merge sort helper in a simpler way, which not only
simplifies the source code but also helps reduce the library size.

10 months agoFix TEST_NEED_PROGRAM to work on old Solaris /bin/sh.
Nick Bowler [Sat, 1 Jul 2023 21:26:08 +0000 (17:26 -0400)]
Fix TEST_NEED_PROGRAM to work on old Solaris /bin/sh.

Solaris /bin/sh does not support ${x##y} expansions.  For this macro
we can almost as easily use a case statement instead.

10 months agoPull in Solaris /bin/sh testsuite fixes from dxcommon.
Nick Bowler [Sat, 1 Jul 2023 21:24:54 +0000 (17:24 -0400)]
Pull in Solaris /bin/sh testsuite fixes from dxcommon.

10 months agoWork around Solaris 8 nawk issue in the test suite.
Nick Bowler [Sat, 1 Jul 2023 19:28:15 +0000 (15:28 -0400)]
Work around Solaris 8 nawk issue in the test suite.

Apparently "nawk" on Solaris 8 does not understand -f- to mean "read
program from standard input", we must spell it as two arguments: -f -

10 months agoAdd missing errmsg.str source file.
Nick Bowler [Sat, 1 Jul 2023 14:27:17 +0000 (10:27 -0400)]
Add missing errmsg.str source file.

Oops, forgot to commit this file.

10 months agolibcdecl: Avoid vsnprintf for error reporting.
Nick Bowler [Fri, 23 Jun 2023 05:11:15 +0000 (01:11 -0400)]
libcdecl: Avoid vsnprintf for error reporting.

Using vsnprintf is overkill here.  We only need to handle a single %s
conversion, which can be done by direct call to snprintf.

As this is the only caller of vsnprintf, dropping it means we can drop
the vsnprintf gnulib module.  Also, at least with gcc, using va_start
and such is fairly expensive.  The direct-snprintf version is quite
a bit more compact.

10 months agolibcdecl: Make cdecl__emit_specs return value usable directly.
Nick Bowler [Fri, 23 Jun 2023 04:39:45 +0000 (00:39 -0400)]
libcdecl: Make cdecl__emit_specs return value usable directly.

Since there is now only one caller of cdecl__emit_specs that cares
about its return value, let's adjust this function to return exactly
what that caller wants, so it doesn't have to do any extra calculation.

10 months agolibcdecl: Accumulate output length in structure.
Nick Bowler [Fri, 23 Jun 2023 04:05:41 +0000 (00:05 -0400)]
libcdecl: Accumulate output length in structure.

Instead of cascading the lengths back via function return values, since
we now have a state structure we can just track the total length in one
place.  This is quite a lot conceptually simpler and cuts out a good
chunk of code.

10 months agolibcdecl: Simplify cdecl__advance.
Nick Bowler [Fri, 23 Jun 2023 03:37:54 +0000 (23:37 -0400)]
libcdecl: Simplify cdecl__advance.

It seems unnecessary to set the dst pointer to null here, nothing
cares if this pointer is null or not null, only the length matters.

10 months agolibcdecl: Use a structure for dst/dstlen in output routines.
Nick Bowler [Fri, 23 Jun 2023 03:25:50 +0000 (23:25 -0400)]
libcdecl: Use a structure for dst/dstlen in output routines.

Since pretty much all the output functions now just directly pass the
dst and dstlen pointers around without touching them in any other way,
it is more efficient to use a structure so there is only one pointer.

10 months agolibcdecl: Rework specifier output logic.
Nick Bowler [Fri, 23 Jun 2023 02:00:34 +0000 (22:00 -0400)]
libcdecl: Rework specifier output logic.

With both the explain and declare code paths using cdecl__emit, we
can give the same treatment to cdecl__explain_specs (now called
cdecl__emit_specs) to simplify things a bit.

This removes the last caller of cdecl__advance, so we can remove
that function (and use this better name for cdecl__advance_).

10 months agolibcdecl: Rework cdecl_declare output logic.
Nick Bowler [Fri, 23 Jun 2023 01:24:19 +0000 (21:24 -0400)]
libcdecl: Rework cdecl_declare output logic.

Instead of adjusting the output pointer/length values after each
internal call, tweak all the functions in declare.c to take an extra
level of indirection so they can just directly adjust the destination
as they go.

10 months agolibcdecl: Rework cdecl_explain output logic.
Nick Bowler [Fri, 23 Jun 2023 01:21:46 +0000 (21:21 -0400)]
libcdecl: Rework cdecl_explain output logic.

Instead of adjusting the output pointer/length values after each
internal call, tweak all the functions in explain.c to take an
extra level of indirection so they can just directly adjust the
destination as they go.

A new helper, cdecl__emit, is provided to simplify the common pattern
of "print a single C string" followed by "advance pointer/length."

10 months agotests: Add canned test case for incomplete arrays.
Nick Bowler [Fri, 23 Jun 2023 01:12:47 +0000 (21:12 -0400)]
tests: Add canned test case for incomplete arrays.

I messed up the whitespace for this while experimenting with the output
routines, and none of the existing test cases noticed.