Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add posix.getopt() interator-based interface #19179

Closed
wants to merge 1 commit into from

Conversation

blblack
Copy link
Contributor

@blblack blblack commented Mar 4, 2024

This implements getopt() in std.posix. It's a bit of an oddball case in some ways that may or may not be worth discussing:

  • getopt(3) is part of the POSIX standard, and widely used in the C/POSIX world, but...
  • It's not really a syscall sort of interface. Its natural implementation is just pure strings-searching code, basically. There are not many such cases yet in os.zig. If this lands in os.zig as posix.getopt(), it maybe makes for an interesting side-point in the discussions around the rename std.os to std.posix #5019 and Eliminate the POSIX API layer #6600.
  • The real POSIX getopt() interface involves global variables and the possibility the caller could unwisely change the arguments on every iteration. This is mostly due to the natural limitations of C. While this Zig getopt supports the same basic mechanics as POSIX to make porting C code easier, it uses an iterator object over constant initial arguments and avoids the global variables. I've seen other minor divergences in this spirit in std.posix already (e.g. nanosleep() doesn't take a struct timespec and internally resumes on EINTR), but our divergence is here is perhaps a bit heavier.

@silversquirl
Copy link
Contributor

I think a simple arg parser in std would be nice, but I don't think it should be getopt, and I especially don't think it should go in std.os or std.posix.
getopt is an interface designed for C, and Zig can do much better. And std.os/std.posix should be kept just for things that involve actually interfacing with the OS - syscall-level stuff, not stuff that's implemented entirely in userspace like this.

@blblack
Copy link
Contributor Author

blblack commented Mar 4, 2024

I think a simple arg parser in std would be nice, but I don't think it should be getopt, and I especially don't think it should go in std.os or std.posix. getopt is an interface designed for C, and Zig can do much better. And std.os/std.posix should be kept just for things that involve actually interfacing with the OS - syscall-level stuff, not stuff that's implemented entirely in userspace like this.

Thanks for the feedback! I have at least some tendency to agree with most of your points, for the most part. I've already seen (and used!), for example https://github.com/Hejsil/zig-clap , which is more in the spirit of a "much better than getopt" argument parser. I'd love to see something more like that in std, somewhere.

My goals here with this patch/debate are really around things like:

  1. Making it simpler for a human to do a 1:1 translation/port of pure C/POSIX code to pure Zig code without having to diverge enough to worry about introducing subtle behavioral changes or new bugs. This proposed getopt interface could serve this purpose somewhere else in std, outside of std.os/std.posix. This code started out in my little test project where I'm keeping C and Zig source for the same program in sync and making them very-identical on purpose, here: https://github.com/blblack/tofurkey .

  2. Providing a concrete point of argument in the debates in the linked issues about the nature and/or future of std.posix. My position is that I think there's value in having a POSIX abstraction layer in Zig. It does make life easier if you're writing somewhat-portable code that's only targeting the *nix/POSIX world. I don't think it really needs to try to do emulation on non-POSIXy targets or be universal in any sense like that. Just lightweight wrappers over the common POSIXy functionality in os/{linux|bsd|etc}.zig that handle minor portability issues within that world. And if you're going to name it POSIX, it may as well target eventually having some implementation of all the normal POSIX stuff, which would include a non-syscall interface like getopt() as well. If you're going to name it "std.unix" instead, things might be different, perhaps, although I'd probably still argue to include it on the basis of (1) above.

@nektro
Copy link
Contributor

nektro commented Mar 4, 2024

I think best case scenario for this patch is it lands in std.c namespace instead of std.posix

@blblack
Copy link
Contributor Author

blblack commented Mar 4, 2024

I think best case scenario for this patch is it lands in std.c namespace instead of std.posix

I'm fine with any logical home for it. On that front though:

I thought std.c was mostly for when libc is linked in? The POSIX-y platforms would already have their own getopt() in libc (although we could use a decl for it, I think), this is for having an easy getopt() work-alike* when porting legacy C applications to native (as in non-libc) Zig.

@nektro
Copy link
Contributor

nektro commented Mar 4, 2024

yes std.c is for when linking with libc and I agree with the above that pure-zig applications should use a more first-principles arg parser instead.

@silversquirl
Copy link
Contributor

Making it simpler for a human to do a 1:1 translation/port of pure C/POSIX code to pure Zig

I think this usecase is niche enough that APIs to support it can go in a third-party package. The standard library should focus on idiomatic Zig interfaces, and low-level OS primitives, rather than emulating C APIs.

@blblack
Copy link
Contributor Author

blblack commented Mar 5, 2024

Well, clearly I'm in the minority here and I'll withdraw. But for the record: the world of C software using legacy POSIX interfaces currently dwarfs the world of idiomatic Zig software. I would have thought that a goal would be to make language ports of existing C software easier in order to foster adoption. Thanks for taking the time!

@blblack blblack closed this Mar 5, 2024
@blblack blblack deleted the getopt branch March 5, 2024 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants