[RFC PATCH v2 14/17] lib: getopt: Merge the optional and required-argument branches

Simon Glass sjg at chromium.org
Wed May 20 01:31:40 CEST 2026


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 <sjg at chromium.org>
---

(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



More information about the U-Boot mailing list