From dfba0fe86d98958611ce76db739a43aa46e25b58 Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Fri, 26 Jul 2019 13:51:22 +0300 Subject: [PATCH] win32: add include/getopt.h with static implementation This is a POSIX compliant implementation of getopt (short options). It passes all tests of gnu getopt in posixly-correct mode, with additional safeguards against out-of-bounds access (optind, optpos). Reset is supported via optind or optreset. For simplicity, the implementation is static at the header, and it uses stdio.h and string.h (could be avoided with some more code). --- win32/include/getopt.h | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 win32/include/getopt.h diff --git a/win32/include/getopt.h b/win32/include/getopt.h new file mode 100644 index 0000000..671a1fc --- /dev/null +++ b/win32/include/getopt.h @@ -0,0 +1,67 @@ +/* + * POSIX compliant getopt + * Copyright (c) 2019 Avi Halachmi (:avih) address@hidden + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GETOPT_H__ +#define __GETOPT_H__ + +#include +#include + +/* + * getopt - POSIX compliant and C90 compatible. + * Notes: + * - To reset after parsing is done (-1 was returned): set optind=1. + * - To reset at any time: set optind=0 or optreset=1. + * - Position within argv[optind] is stored at optpos between invocations. + * - Safeguards out of bounds access (optind, optpos) regardless of anything. + * - Uses stdio.h and string.h for simplicity, could be avoided with more code. + */ + +static char *optarg = 0; +static int opterr = 1, optind = 1, optopt = '?', optpos = 1, optreset = 0; +static int getopt(int argc, char *const argv[], const char *optstring); + +int getopt(int c, char *const v[], const char *s) { + char *vi; int e; + if (optind <= 0 || optreset) + optpos=optind=1, optreset=0; + vi = optind < c ? v[optind] : 0; + if (!vi || vi[0] != '-' || !vi[1]) + return optpos=1, -1; + if (vi[1] == '-' && !vi[2]) + return optind++, optpos=1, -1; + if (optpos < 1 || optpos >= strlen(vi)) + optpos = 1; + +#define msg(m) opterr && e && fprintf(stderr, "%s: %s -- %c\n", *v, m, optopt) + optarg=0, optopt=vi[optpos], e=(*s != ':'); + if (!vi[++optpos]) + optind++, optpos=1; + for (; *s && *s != optopt; s++); + if (!*s || *s == ':') + return msg("illegal option"), '?'; + if (s[1] != ':') + return *s; + if (optind == c) + return msg("option requires an argument"), (e ? '?' : ':'); + return optarg=v[optind]+(optpos > 1 ? optpos : 0), optind++, optpos=1, *s; +#undef msg +} + +#endif /* __GETOPT_H__ */ -- 2.22.0