Hacker News new | past | comments | ask | show | jobs | submit login

In general I agree with your sentiment, but getopt is one where I'm willing to make an exception. getopt_long is barely any actual code, and honestly its design stinks for an argument parser. It's also just standard C (IE. No platform issues to worry about assuming you're going to get argv and argc). I've written my own argument parser in just around 100 lines that's pretty similar to getopt and so far it's been well worth it.



Does your hand-written parser handle all the corner cases getopt does? Ending option processing with "--"? Interleaving options in any order (ls foo -l)? Stacking short options (ls -la) or writing them separately (ls -l -a)?


I had to go check if it does '--', but yes it does all of those things you listed. My parser is similar to getopt, but it's less clunky and avoids the duplication that getopt_long results in.


Thank you for your diligence, then; most hand-written parsers fail one or more of those.

> less clunky and avoids the duplication that getopt_long results in.

Duplication because of the ugly flag/val logic, which in practice is typically passed as either NULL, 's' (long option for short option 's') or NULL, OPTION_FOO (long option with no short option, OPTION_FOO > 255)?

Yeah, that does seem silly. I think they did that to simplify the setting of boolean parameters, by passing &some_flag, 1, but that seems woefully insufficient when you need to handle arguments. I'd love to have a C library as capable as Python's argparse, instead.


Of course, I wasn't going to half-do it if I was gonna replace getopt. I'm with you in that I get annoyed when I run into programs which do just half-done job at a getopt replacement and you can't do the normal stuff like "-df" instead of "-d -f".

And yes, that's pretty much what I'm getting at. The issue really stems down to the fact that getopt_long is just bolted on to getopt, so there's still the string short-opt syntax like "sf:t", and then you duplicate the options in the array of long opts with the chars or some random number > 255 otherwise. The string is really the most annoying part because there's no good way to generate it via the C preprocessor that I could come-up with, leading to some duplication between the long-opts and short-opts. It also can't easily generate help text for you from your arguments, which bugged me. My argument parser basically works off of a single xmacro header that holds all the argument information for getopt (Which gets organized via a few macros into an enum and an array). It's dead simple to add new arguments and there's no duplication or separate strings or etc. that you have to update at the same time besides adding code to handle that argument.

Personally, I wrote my argument parser specifically because I couldn't find any that I was happy with after looking around. They were either clunky to use (getopt_long), or were full libraries and seemed like it would be a hassle to get it integrated into my code. I'd love to see a 'standard' argument parser that works with long options well and doesn't just feel like an afterthought like it does with getopt_long, but I think the chance to make such a thing has been missed. Personally, if I would ever use such a thing then it needs to be a single or just a few .c and .h files that I can stick directly into my program. I wouldn't want to have to bet on the distribution having it or not, and I'm not going to add a separate dependency just for argument parsing.


Is this parser open source? If so, why not post a link?


Well you can find it in here: https://github.com/DSMan195276/cmips

I don't have it as a separate project specifically for the argument parser which is why I didn't link to it. But the meat of the parser is in ./common/arg_parse.c, with the header for it in ./include/common/arg_parse.h. If you want to throw it into your own project you'll want to take a quick look through the ./arg_parse.c and modify it to suit your project (The help text specifically is for my program, so you'll want to rewrite the text in that part).

You can see an 'example' usage in the same repo. The files listed below parse the arguments into a single struct with few flags inside, and also look for filenames in the arguments to load into the emulator:

    ./cmips/args.c
    ./cmips/args.h
    ./cmips/args.x
./cmips/args.x is a xmacro header. It mostly just contains the contents of the struct arg array for this program, but it's also used to create enum entries which index the struct arg array. The 'parse_args' function is fairly similar to what you'd do with getopt, just with the 'arg_parser' function instead.

The argument parser code could probably be improved. Just looking back at it, it's got a bit to much logic going on in that single function, it could probably be split up a bit. I'm gonna be working on this project again pretty soon I think, so I might fix up this parser along with it.


Thanks for sharing. I was going to suggest you make the relevant files available as lgpl -- but then I went and looked for getopt.c, and discovered that it's in the util-linux package and is also gplv2 (the version that I had installed, see more below). I'm normally a great fan of copyleft and the full gpl (rather than lgpl/bsd/mit etc) -- but it does strike me as a little strange to have something like this under the gpl -- it "feels" to me like more of a libc-thing (not really talking about your code in particular, as that is part of a different program anyway).

However, the getopt.h-file in the actual gnu libc-package (libc6-dev) is lgpl.

Interestingly, the getopt.c/.h in gnulib (gnu portability library) appear to both be gpl, not lgpl.


My code is just under GPL because I just wrote it as part of another program that's also GPL. That said, I'd be happy to re-license it as LGPL since I'm the only one who's touched that code, but since you'd probably want to drop it in to another program instead of compiling it as a library it wouldn't make much of a difference.

I've seen a few getopt.c implementations that are MIT I believe.

Personally I'm guessing that those getopt implementations are probably all different (Just because it hardly takes any time to write one). AFAIK gnulib is GPL itself, so the getopt inside was just licensed GPL too, same thing for util-linux. libc is LGPL though, so that getopt.c was licensed as LGPL. It is kinda curious though, I'm personally just surprised that there are so many implementations of the same thing.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: