gout

A static git page generator
git clone https://git.bracken.jp/gout.git
Log | Files | Refs | README | LICENSE

commit d429e285091db54f4b2d2bea157bd28a28355a93
parent dae746f33d9c8ad926eff935370e0f34ee91ac50
Author: Chris Bracken <chris@bracken.jp>
Date:   Fri, 20 Feb 2026 19:05:05 +0900

options: migrate to getopt

Diffstat:
Msrc/gout.c | 94++++++++++++++++++++++++++++++++++++-------------------------------------------
Msrc/gout_index.c | 45++++++++++++++++++++++++++++-----------------
2 files changed, 71 insertions(+), 68 deletions(-)

diff --git a/src/gout.c b/src/gout.c @@ -4,6 +4,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include "git/commit.h" #include "git/file.h" @@ -27,62 +28,53 @@ GoutOptions* gout_options_create(int argc, const char* argv[]) { .baseurl = "", .writer_type = kRepoWriterTypeHtml, }; - for (int i = 1; i < argc; i++) { - if (argv[i][0] != '-') { - // Cannot specify more than one repo directory. - if (options.repodir) { - return NULL; - } - options.repodir = argv[i]; - } else if (argv[i][1] == 'c') { - // Cache the entries of the log page up to the point of the last commit. - // The cachefile will store the last commit id and the entries in the - // HTML table. It is up to the user to make sure the state of the - // cachefile is in sync with the history of the repository. - - // Mutually exclusive with -l. - if (options.log_commit_limit > 0) { - return NULL; - } - // Requires cachefile path argument. - if (i + 1 >= argc) { - return NULL; - } - options.cachefile_path = argv[++i]; - } else if (argv[i][1] == 'l') { - // Write a maximum number of commits to the log.html file only. However - // the commit files are written as usual. - - // Mutually exclusive with -c option. - if (options.cachefile_path) { - return NULL; - } - // Requires log commits argument. - if (i + 1 >= argc) { - return NULL; - } - errno = 0; - char* p; - options.log_commit_limit = strtoll(argv[++i], &p, 10); - if (!argv[i][0] || *p || options.log_commit_limit <= 0 || errno) { - return NULL; - } - } else if (argv[i][1] == 'u') { - // Requires log commits argument. - if (i + 1 >= argc) { + + int ch; + optind = 1; + opterr = 0; + while ((ch = getopt(argc, (char* const*)argv, "c:l:u:HG")) != -1) { + switch (ch) { + case 'c': + // Mutually exclusive with -l. + if (options.log_commit_limit > 0) { + return NULL; + } + options.cachefile_path = optarg; + break; + case 'l': + // Mutually exclusive with -c. + if (options.cachefile_path) { + return NULL; + } + errno = 0; + char* p; + options.log_commit_limit = strtoll(optarg, &p, 10); + if (!optarg[0] || *p || options.log_commit_limit <= 0 || errno) { + return NULL; + } + break; + case 'u': + options.baseurl = optarg; + break; + case 'H': + options.writer_type = kRepoWriterTypeHtml; + break; + case 'G': + options.writer_type = kRepoWriterTypeGopher; + break; + default: return NULL; - } - options.baseurl = argv[++i]; - } else if (argv[i][1] == 'H') { - options.writer_type = kRepoWriterTypeHtml; - } else if (argv[i][1] == 'G') { - options.writer_type = kRepoWriterTypeGopher; } } - // Must specify at least one repo directory. - if (!options.repodir) { + argc -= optind; + argv += optind; + + // Must specify exactly one repo directory. + if (argc != 1) { return NULL; } + options.repodir = argv[0]; + GoutOptions* options_out = ecalloc(1, sizeof(GoutOptions)); *options_out = options; return options_out; diff --git a/src/gout_index.c b/src/gout_index.c @@ -4,6 +4,7 @@ #include <err.h> #include <stddef.h> #include <stdlib.h> +#include <unistd.h> #include "git/git.h" #include "security.h" @@ -21,26 +22,36 @@ GoutIndexOptions* gout_index_options_create(int argc, const char* argv[]) { .me_url = NULL, .writer_type = kIndexWriterTypeHtml, }; - for (int i = 1; i < argc; i++) { - if (argv[i][0] != '-') { - options.repo_dirs = reallocarray( - options.repo_dirs, options.repo_dir_count + 1, sizeof(char*)); - if (!options.repo_dirs) { - err(1, "reallocarray"); - } - options.repo_dirs[options.repo_dir_count++] = argv[i]; - } else if (argv[i][1] == 'm') { - // Requires 'me' URL argument. - if (i + 1 >= argc) { + + int ch; + optind = 1; + opterr = 0; + while ((ch = getopt(argc, (char* const*)argv, "m:HG")) != -1) { + switch (ch) { + case 'm': + options.me_url = optarg; + break; + case 'H': + options.writer_type = kIndexWriterTypeHtml; + break; + case 'G': + options.writer_type = kIndexWriterTypeGopher; + break; + default: return NULL; - } - options.me_url = argv[++i]; - } else if (argv[i][1] == 'H') { - options.writer_type = kIndexWriterTypeHtml; - } else if (argv[i][1] == 'G') { - options.writer_type = kIndexWriterTypeGopher; } } + argc -= optind; + argv += optind; + + if (argc > 0) { + options.repo_dirs = ecalloc(argc, sizeof(char*)); + for (int i = 0; i < argc; i++) { + options.repo_dirs[i] = argv[i]; + } + options.repo_dir_count = argc; + } + GoutIndexOptions* options_out = ecalloc(1, sizeof(GoutIndexOptions)); *options_out = options; return options_out;