Both branches start with the same 'argument in same argv[] element'
test and the same advance-to-next-element bookkeeping; only the
behaviour when the argument is missing differs. Fold them into one
sequence and decide between ':' (required) and gs->arg=NULL
(optional) at the single missing-argument point.

The four cases of the original optional-argument block (in-element
arg, last-element-no-arg, next-element-arg, next-element-dash) all
collapse onto the same code path used by the required-argument
branch, with the curoptp[2] check determining only the error vs
optional-absent outcome.

Saves about 80 bytes on sandbox, similar on arm64. No functional
change; the lib_test_getopt unit tests still pass.

Signed-off-by: Simon Glass <[email protected]>
---

(no changes since v1)

 lib/getopt.c | 49 ++++++++++++++-----------------------------------
 1 file changed, 14 insertions(+), 35 deletions(-)

diff --git a/lib/getopt.c b/lib/getopt.c
index 5e907477e57..b3ad6968f8d 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -97,46 +97,19 @@ int getopt(struct getopt_state *gs, const char *optstring)
                return '?';
        }
 
-       if (*(curoptp + 1) != ':') {
+       if (curoptp[1] != ':') {
                /* option with no argument. Just return it */
                gs->arg = NULL;
                gs->arg_index++;
                return curopt;
        }
 
-       if (curoptp[2] == ':') {
-               /* optional argument */
-               if (argv[gs->index][gs->arg_index + 1]) {
-                       /* optional argument with directly following arg */
-                       gs->arg = argv[gs->index++] + gs->arg_index + 1;
-                       gs->arg_index = 1;
-                       return curopt;
-               }
-               if (gs->index + gs->nonopts + 1 == argc) {
-                       /* We are at the last argv[] element */
-                       gs->arg = NULL;
-                       gs->index++;
-                       return curopt;
-               }
-               if (*argv[gs->index + 1] != '-') {
-                       /*
-                        * optional argument with arg in next argv[] element
-                        */
-                       gs->index++;
-                       gs->arg = argv[gs->index++];
-                       gs->arg_index = 1;
-                       return curopt;
-               }
-
-               /* no optional argument found */
-               gs->arg = NULL;
-               gs->arg_index = 1;
-               gs->index++;
-               return curopt;
-       }
-
+       /*
+        * Option takes an argument. The argument may be in the same argv[]
+        * element (``-fXXX``) or in the next one (``-f XXX``); a ``::`` in
+        * optstring marks the argument optional.
+        */
        if (argv[gs->index][gs->arg_index + 1]) {
-               /* required argument with directly following arg */
                gs->arg = argv[gs->index++] + gs->arg_index + 1;
                gs->arg_index = 1;
                return curopt;
@@ -146,8 +119,14 @@ int getopt(struct getopt_state *gs, const char *optstring)
        gs->arg_index = 1;
 
        if (gs->index + gs->nonopts >= argc || argv[gs->index][0] == '-') {
-               gs->opt = curopt;
-               return ':';
+               if (curoptp[2] != ':') {
+                       /* required argument is missing */
+                       gs->opt = curopt;
+                       return ':';
+               }
+               /* optional argument absent */
+               gs->arg = NULL;
+               return curopt;
        }
 
        gs->arg = argv[gs->index++];
-- 
2.43.0

Reply via email to