Skip to content

Add generator for popt option tables#40624

Closed
keszybz wants to merge 128 commits into
systemd:mainfrom
keszybz:arg-generation
Closed

Add generator for popt option tables#40624
keszybz wants to merge 128 commits into
systemd:mainfrom
keszybz:arg-generation

Conversation

@keszybz

@keszybz keszybz commented Feb 10, 2026

Copy link
Copy Markdown
Member

The basic idea is that we'll have "one source of truth" for the list of options. Currently, this is split between:
1. struct option options[] array for long options
2. the short option parameter to getopt_long()
3. --help
so it is easy to forget to add or update one of those places where appropriate.

The code is easier to read when various parts are written in the same order. This is true even for the generated code, which is properly formatted and should be as readable as the original.

Using a generator allows us to define various parts of the boilerplate just once. Over time, if we discover that the same pattern is used in multiple files, we can move it to the generator.

A file is generated with C code, and that file is #include'd. With this approach, we can lift the existing parsing code with no changes or with some small changes. If instead the generated code was designed to be a standalone file, we'd need to at least make all arg_* variables non-static and rework the code in other ways. This would create a lot of churn but would otherwise be of little benefit.

This would be the first phase. The second phase would be get the remaining instances of parse_argv converted. And then we can extend this approach to e.g. verb handling, i.e. have a similar scheme where the verbs are listed in the .args file and help and the verb table are generated. Then we can declare how many args a program takes and make the check for that automatic. (Currently, quite a few programs that don't require arguments simply ignore any positional arguments.) And finally, we should be able to use this as a basic for autogenerated tab completions.

keszybz and others added 26 commits February 11, 2026 11:59
I didn't want to do this, but in some cases this seems to be the best
option overall.
--help is the same, except for the reordering of a few options,
BOOLEAN → yes|no, additions of "|help" in a few places, rewordings.
This allows multiple parsers to be used in a single .c file.
Let's call the file in src/shared with the usual -util.[ch] suffix.
Then the tool doesn't need a special suffix and things are move obvious.
The help strings are changed to conform to a uniform pattern: all
options that tell the tool to wait for something are described as
"require …". Previously we said "block until", "required", "requires",
and "wait until", which makes it harder to see that those are all
conceptually similar options.
The handling of the path argument is changed so that we can print the
default value more naturally.
--system is now documented, fixup for original addition
in 450442c.
There are some in differences in --help, apart from ordering changes and
minor rewordings:
  - --match=, -A, -T, -N are now documented
  - --fido2-credential-algorithm= is documented
  - short options -I, -k, -s, -e are listed

Error string for --match is fixed.

'arg_languages' is renamed to just 'languages'. It's just a local variable.
Now seems to work fine with versions 3.9—3.15.
I forgot that we need to do that :(
Returning EXIT_* from an inner function is unusual and better
avoided. Let's just return a negative value and let the caller
to the conversion.
@keszybz

keszybz commented Feb 11, 2026

Copy link
Copy Markdown
Member Author

I split out cleanups&fixes into #40641. This PR now includes those commits in the beginning and the remaining ones on top. I added compat for older Python versions and also added conversion of the new report tool.

Comment thread tools/make_argv_parser.py
# The file is a sequence of 'option' statements, listing the short and long option names.
# Names may be followed by '=' to specify that the option takes parameters.
# The use of '=' must be consistent, i.e. all are none names must use it.
# At most of the the names with '=' may be followed by the argument name.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broken sentence?

Comment thread tools/make_argv_parser.py
#
# After the 'option' line, one or more 'help' lines specify the string for --help.
# This string will be wrapped to fit in the available number of columns,
# specified b TARGET_LINE_WIDTH.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

5 participants