{"id":28396972,"url":"https://github.com/hroptatyr/yuck","last_synced_at":"2025-06-27T13:31:38.069Z","repository":{"id":12157658,"uuid":"14752149","full_name":"hroptatyr/yuck","owner":"hroptatyr","description":"Your Umbrella Command Kit, a bog-standard command line option parser for C with all the knickknackery and whatnots.","archived":false,"fork":false,"pushed_at":"2024-09-03T10:23:31.000Z","size":754,"stargazers_count":62,"open_issues_count":2,"forks_count":7,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-06-01T09:46:19.742Z","etag":null,"topics":["c","option-parser","yuck"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hroptatyr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-11-27T16:18:22.000Z","updated_at":"2025-05-13T10:41:49.000Z","dependencies_parsed_at":"2022-09-24T10:50:32.371Z","dependency_job_id":null,"html_url":"https://github.com/hroptatyr/yuck","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/hroptatyr/yuck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hroptatyr%2Fyuck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hroptatyr%2Fyuck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hroptatyr%2Fyuck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hroptatyr%2Fyuck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hroptatyr","download_url":"https://codeload.github.com/hroptatyr/yuck/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hroptatyr%2Fyuck/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262265141,"owners_count":23284452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","option-parser","yuck"],"created_at":"2025-05-31T23:39:03.843Z","updated_at":"2025-06-27T13:31:38.060Z","avatar_url":"https://github.com/hroptatyr.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"yuck\n====\n\n[![Build Status](https://secure.travis-ci.org/hroptatyr/yuck.png?branch=master)](http://travis-ci.org/hroptatyr/yuck)\n[![Licence](http://img.shields.io/badge/licence-BSD3c-brightgreen.svg)](http://opensource.org/licenses/BSD-3-Clause)\n\n+ project homepage: http://www.fresse.org/yuck/\n+ github page: https://github.com/hroptatyr/yuck\n+ downloads: https://github.com/hroptatyr/yuck/releases\n+ issues: https://github.com/hroptatyr/yuck/issues\n\n### Your Umbrella Command Kit\n\nyuck is a bog-standard command line option parser for C that works with\nonly household ingredients (a C compiler and the m4 macro processor) and\ncomes with all the knickknackery and whatnots:\n\n+ GNU-style long options (`--blah`)\n+ condensable short options (`-xab` for `-x -a -b`)\n+ optional arguments to long and short options (--foo[=BAR])\n+ multiple occurrence of options (-vvv)\n+ does *not* depend on libc's getopt() nor getopt_long()\n+ licensed under [BSD 3-clause licence][4]\n\nAnd getting started is as easy as *munching* cake -- let yuck do the\nactual baking for you:  Just feed it the `--help` output you'd like to\nsee and yuck will happily try and generate a parser from it.\n\nTo build yuck from the git sources:\n\n    $ autoreconf -fi\n    $ ./configure\n    $ make\n    $ make install\n\nFor tarball builds omit the `autoreconf -fi` line.\n\n\nThat all? I need more highlights\n--------------------------------\n\nyuck can also generate parsers for umbrella tools, i.e. tools that take\na command as argument (think git(1), ip(8), etc.).\n\nyuck has no exotic build time or run time dependencies, a C99 compiler and\nthe m4 macro processor is enough.\n\nyuck can be used in other projects by copying 4 files and setting up\na simple Makefile rule.\n\nyuck can generate man pages based on the definition files (the --help\noutput), much like [help2man](http://www.gnu.org/s/help2man/).\n\nyuck can automatically determine (and make use of) version numbers in\ngit controlled projects.\n\n\nBut why?\n--------\nThere's [AutoOpts](http://autogen.sourceforge.net/autoopts.html),\nthere's [gengetopt](http://www.gnu.org/software/gengetopt/), lately even\nglibc takes on arg parsing (see their argp section in the manual); makes\nyou wonder how we dare create yet another thing for something as simple\nas command line argument parsing.\n\nWell, the killer feature, as we see it, is yuck's approach to specifying\nthe parser in question.  You expect your users to grasp your `--help`\noutput?  Well, there you go, if your users can understand it so can you!\nJust type up what you'd like to see in your `--help` output and yuck\nwill generate a parser that does exactly that.\n\n\nNo, the other why?\n------------------\nyuck has been crafted by a heavy gengetopt user, so both the procedure\nand the handling is quite similar to the ggo workflow.\n\nWhile gengetopt does a great job most of the time, it becomes annoying\nin some corner cases, is largely undermaintained, counts on libc for the\nactual getopt()'ing, is GPL licensed but first and foremost it is\ncertainly not the right tool for the job if the job is parsing options\nfor umbrella programs.\n\n\nAnd what about docopt?\n----------------------\nWhile [docopt](http://docopt.org/) is based on essentially the same idea\nas yuck, its grammar is formal and doesn't allow for descriptive texts.\nAlso, docopt's C parser (yuck's primary target) is not fully functional.\n\nHowever, if you're currently using docopt and you feel comfortable with\nit, there's no need to switch to yuck.\n\n\nGot an example?\n---------------\nConsider the following .yuck file:\n\n    Usage: xmpl\n    Shows off yuck.\n\n      -x, --extra        Produce some extra bling.\n      -o, --output=FILE  Output bling to file.\n\nProcess with:\n\n    $ yuck gen xmpl.yuck \u003e xmpl.yucc\n\nThen include in your `xmpl.c`:\n\n    #include \u003cstdio.h\u003e\n    #include \"xmpl.yucc\"\n\n    int main(int argc, char *argv[])\n    {\n            yuck_t argp[1];\n    \n            yuck_parse(argp, argc, argv);\n    \n            if (argp-\u003eextra_flag) {\n                    puts(\"BLING BLING!\");\n            }\n    \n            yuck_free(argp);\n            return 0;\n    }\n\nAnd that's it.  Some example calls:\n\n    $ xmpl --help\n    Usage: xmpl [OPTION]...\n\n    Shows off yuck.\n\n      -h, --help            display this help and exit\n      -V, --version         output version information and exit\n      -x, --extra           Produce some extra bling.\n      -o, --output=FILE     Output bling to file.\n\n    $ xmpl -x\n    BLING BLING!\n    $\n\nMore details, please\n--------------------\nThe example above results in an auxiliary struct:\n\n    struct yuck_s {\n            enum yuck_cmds_e cmd;\n    \n            /* left-over arguments, the command string is never a part of this */\n            size_t nargs;\n            char *const *args;\n    \n            /* slots common to all commands */\n    \n            /* help is handled automatically */\n            /* version is handled automatically */\n            unsigned int extra_flag;\n            const char *output_arg;\n    };\n\nwhich is filled in when `yuck_parse()` is run.  As there are no\nsubcommands defined this struct will directly be typedef'd to `yuck_t`\nand the `cmd` slot at the top will always hold `YUCK_NOCMD`.\n\nEvery occurrence of `-x` or `--extra` on the command line will increase\nthe count in `extra_flag`, yuck does not distinguish between optional\nflags (to occur at most once), flags to occur exactly once, or flags\nthat can occur multiple times.\n\nSame goes for every occurrence of `-o` or `--output`, however, the\npointer in `output_arg` will point to the last occurrence on the\ncommandline.\n\nLeft-over positional arguments will be counted in `nargs` and collected\ninto `args`.  It is never an error to pass in positional arguments.  It\nis up to the caller of `yuck_parse()` to check the yuck_t representation\nof the command line for integrity.\n\nIn a similar fashion, yuck's only types are options with arguments\n(which are mapped to const char* or const char** in case of multi-args)\nand flags (mapped to unsigned int, representing the number of occurrences\non the command line).  Again, it is up to the postprocessing code to\ninterpret arguments suitably, e.g. convert integer strings to integers,\nor constrain a HOSTNAME argument to its legal characters, etc.\n\nAll const char* objects point straight to members of `argv`, i.e. they\nare not `strdup()`ed.  Changing strings in argv will therefore change\nthe strings in the yuck_t representation also, and vice versa (after\nby-passing the const qualifier).\n\n\nSo what about subcommands?\n--------------------------\nyuck's command-line interface is generated by yuck itself, so for an\nhands-on example have a look there.\n\nSubcommands are specified through extra usage clauses:\n\n    Usage: xmpl\n    Shows off yuck.\n    \n      -x, --extra        Produce some extra bling.\n      -o, --output=FILE  Output bling to file.\n    \n    Usage: xmpl turbo [FILE]...\n    Run xmpl in turbo mode\n    \n      -x, --extra-turbo  Use more turbos than normal.\n\nAgain, generate a C parser:\n\n    $ yuck gen xmpl-subcommands.yuck\n\nThe auxiliaries generated will now look like:\n\n    typedef union yuck_u yuck_t;\n    \n    /* convenience structure for `turbo' */\n    struct yuck_cmd_turbo_s {\n            enum yuck_cmds_e cmd;\n    \n            /* left-over arguments, the command string is never a part of this */\n            size_t nargs;\n            char *const *args;\n    \n            /* help is handled automatically */\n            /* version is handled automatically */\n            unsigned int extra_flag;\n            const char *output_arg;\n    \n            unsigned int extra_turbo_flag;\n    };\n    \n    union yuck_u {\n            /* generic struct */\n            struct {\n                    enum yuck_cmds_e cmd;\n    \n                    /* left-over arguments,\n                     * the command string is never a part of this */\n                    size_t nargs;\n                    char *const *args;\n    \n                    /* slots common to all commands */\n                    /* help is handled automatically */\n                    /* version is handled automatically */\n                    unsigned int extra_flag;\n                    const char *output_arg;\n            };\n    \n            /* depending on CMD at most one of the following structs is filled in\n             * if CMD is YUCK_NONE no slots of this union must be accessed */\n            struct yuck_cmd_turbo_s turbo;\n    };\n\nand when `yuck_parse()` is run, provided the `turbo` command is given,\nthe struct yuck_cmd_turbo_s object will be filled in, `cmd` will be set\nto `XMPL_CMD_TURBO` in such case.  If no command is given the generic\nstruct at the top of the union will be filled in and `cmd` is set to\n`XMPL_CMD_NONE`.\n\nThe structs are carefully generated in a way that allows you to simple\ncast a `yuck_t*` to a `struct yuck_cmd_turbo_s*`.\n\n\nAnd now handing the `--help` output over to help2man again?!\n------------------------------------------------------------\nNope.  Of course not.  If we can create something as formal and\ndefinitive as a command-line option parser, we sure as hell can create\nsomething sloppy and informal as a man page (that is, no offence, for\nhuman eyes only anyway).\n\nyuck comes with a template `yuck.man.m4` for that purpose which is\nmaterialised through the `genman` command:\n\n    $ yuck genman xmpl-subcommands.yuck\n\nwould produce [xmpl-subcommands.man](xmpl-subcommands.html) (which here\nfor obvious reasons has been run through man2html first).\n\n\nThis is all superfluous and utter rubbish because ...\n-----------------------------------------------------\nDon't let me stop you there.  I'm all ears for feature requests, patches,\ncriticism and insults, oh, and death threats, of course.\n\nBest to use the [bug tracker][1], or drop me an [email][2], or just put\na huuuge graffiti [on my house][3].\n\n  [1]: https://github.com/hroptatyr/yuck/issues\n  [2]: mailto:devel+yuck@fresse.org\n  [3]: http://www.fresse.org/yuck/my-house.jpg\n  [4]: http://opensource.org/licenses/BSD-3-Clause\n\n\u003c!--\n  Local variables:\n  mode: auto-fill\n  fill-column: 72\n  filladapt-mode: t\n  End:\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhroptatyr%2Fyuck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhroptatyr%2Fyuck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhroptatyr%2Fyuck/lists"}