Hacker News new | ask | show | jobs
by mtlmtlmtlmtl 1264 days ago
ARG_BEGIN opens a switch statement. So it can enter any of the cases, or it'll jump to the else if part.
1 comments

Is there any reason this is not written as `switch(..) { <case statements>; default: <else statements> }`. I.e is there a reason for `if(0)`?
The whole `if` portion is for if the second character of the argument (after the initial `-`) is a second `-` [0].

In that case, the switch jumped to `case '-':` hidden within the macro, and the if statement is about processing long arguments (like `--help`). arguments only available as a short flag should never get executed as part of a short flag, so putting them inside the if(0) case is an easy option.

An alternative without if(0) of any variety would be:

    ARG_BEGIN {
            if (ARG_LONG("reverse")) case 'r': {
                    reverse = 1;
                    ARG_FLAG();
            } else if (ARG_LONG("input")) case 'i': {
                    input = ARG_VAL();
            } else if (ARG_LONG("output")) case 'o': {
                    output = ARG_VAL();
            } else if (ARG_LONG("help")) case 'h': case '?': {
                    printf("Usage: %s [OPTION...] [STRING...]\n", argv0);
                    puts("Example usage of arg.h\n");
                    puts("Options:");
                    puts("  -a,                set a to true");
                    puts("  -b,                set a to true");
                    puts("  -c,                set a to true");
                    puts("  -r, --reverse      set reverse to true");
                    puts("  -i, --input=STR    set input string to STR");
                    puts("  -o, --output=STR   set output string to STR");
                    puts("  -h, --help         display this help and exit");
                    return EXIT_SUCCESS;
            } else { default:
                    fprintf(stderr,
                            "%s: invalid option '%s'\n"
                            "Try '%s --help' for more information.\n",
                            argv0, *argv, argv0);
                    return EXIT_FAILURE;
            }
            break;
            case 'a': a = 1; ARG_FLAG(); break;
            case 'b': b = 1; ARG_FLAG(); break;
            case 'c': c = 1; ARG_FLAG(); break;
            case '\0': readstdin = 1; break;
    } ARG_END;
  
The downside is that those few short flag only arguments no longer line up nicely with the others, and they come after the default, which could be a little bit confusing.

Footnote: [0] Except if that second dash is the last character of the argument, in which case -- is the end of flags marker, meaning any further arguments that begin with `-` are just funky positional paramaters