# lacheck is confused when curly brackets are inside a \newcommand

Karl Berry karl at freefriends.org
Sun May 1 00:18:28 CEST 2022

Hi Michael - thanks again for the report.

\newcommand{\boldx}[1]{{\bf #1}}
\newcommand{\ibx}[1]{\textbf{\textit{#1}}}
...
"foo.tex", line 1: <- unmatched "}"

The immediate problem was that the { that starts the definition was
swallowed up by the pattern that started the definition. Hence the {
vs. } count mismatch. That is easy enough to fix, by incrementing the
count an extra time at the beginning.

Then there was a second problem that if a } was missing, no error was
reported. That is, if the def_group variable counting braces wasn't zero
at the end of the file. So I added:
<<EOF>> {
if (def_count != 0)
{
printf("\"%s\", line %d: %d missing right brace(s).\n",
file_name, line_count, def_count);
}

Then I noticed that the pattern matching \newcommand etc. did not try to
handle the * form of definitions, or the [N] argument count, or the
[dflt] optional argument default. Foolishly, I tried to add all that.
The regular expression is now pretty much a monster. (Unfortunately
[f]lex does not support "readable" regexps as in Perl's /x, as far as I
know.)

I feel almost certain that I introduced bugs somewhere in all that.
Here is what the regexp looks like now, together with a sort-of "human
translation" of the pieces I wrote for myself.

"\\"(provide|(re)?newcommand)[ \t\n]*(\*[ \t\n]*)?(\{\$^}]+\}|\\([a-zA-Z]+|.))[ \t\n]*(\[[0-9]$($[^]]*$)?)?[ \t\n]*[^{]*\{	{ ++def_count; BEGIN(DEF); }

/*                          ws     optional*    ({\cs}      |\cs)                     [N]?      [dflt]?             .*     {defn}
... */

I committed the changes in TL r63190, and bumped the lacheck version to 1.30.

I don't want to commit a new binary, but I made one for x86_64-linux and
put it at http://tug.org/~karl/lacheck-220501.gz for anyone who'd like
to give it a try. It doesn't depend on kpathsea or anything else, so