uboot/lib/getopt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * getopt.c - a simple getopt(3) implementation. See getopt.h for explanation.
   4 *
   5 * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
   6 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
   7 */
   8
   9#define LOG_CATEGORY LOGC_CORE
  10
  11#include <common.h>
  12#include <getopt.h>
  13#include <log.h>
  14
  15void getopt_init_state(struct getopt_state *gs)
  16{
  17        gs->index = 1;
  18        gs->arg_index = 1;
  19}
  20
  21int __getopt(struct getopt_state *gs, int argc, char *const argv[],
  22             const char *optstring, bool silent)
  23{
  24        char curopt;   /* current option character */
  25        const char *curoptp; /* pointer to the current option in optstring */
  26
  27        while (1) {
  28                log_debug("arg_index: %d index: %d\n", gs->arg_index,
  29                          gs->index);
  30
  31                /* `--` indicates the end of options */
  32                if (gs->arg_index == 1 && argv[gs->index] &&
  33                    !strcmp(argv[gs->index], "--")) {
  34                        gs->index++;
  35                        return -1;
  36                }
  37
  38                /* Out of arguments */
  39                if (gs->index >= argc)
  40                        return -1;
  41
  42                /* Can't parse non-options */
  43                if (*argv[gs->index] != '-')
  44                        return -1;
  45
  46                /* We have found an option */
  47                curopt = argv[gs->index][gs->arg_index];
  48                if (curopt)
  49                        break;
  50                /*
  51                 * no more options in current argv[] element; try the next one
  52                 */
  53                gs->index++;
  54                gs->arg_index = 1;
  55        }
  56
  57        /* look up current option in optstring */
  58        curoptp = strchr(optstring, curopt);
  59
  60        if (!curoptp) {
  61                if (!silent)
  62                        printf("%s: invalid option -- %c\n", argv[0], curopt);
  63                gs->opt = curopt;
  64                gs->arg_index++;
  65                return '?';
  66        }
  67
  68        if (*(curoptp + 1) != ':') {
  69                /* option with no argument. Just return it */
  70                gs->arg = NULL;
  71                gs->arg_index++;
  72                return curopt;
  73        }
  74
  75        if (*(curoptp + 1) && *(curoptp + 2) == ':') {
  76                /* optional argument */
  77                if (argv[gs->index][gs->arg_index + 1]) {
  78                        /* optional argument with directly following arg */
  79                        gs->arg = argv[gs->index++] + gs->arg_index + 1;
  80                        gs->arg_index = 1;
  81                        return curopt;
  82                }
  83                if (gs->index + 1 == argc) {
  84                        /* We are at the last argv[] element */
  85                        gs->arg = NULL;
  86                        gs->index++;
  87                        return curopt;
  88                }
  89                if (*argv[gs->index + 1] != '-') {
  90                        /*
  91                         * optional argument with arg in next argv[] element
  92                         */
  93                        gs->index++;
  94                        gs->arg = argv[gs->index++];
  95                        gs->arg_index = 1;
  96                        return curopt;
  97                }
  98
  99                /* no optional argument found */
 100                gs->arg = NULL;
 101                gs->arg_index = 1;
 102                gs->index++;
 103                return curopt;
 104        }
 105
 106        if (argv[gs->index][gs->arg_index + 1]) {
 107                /* required argument with directly following arg */
 108                gs->arg = argv[gs->index++] + gs->arg_index + 1;
 109                gs->arg_index = 1;
 110                return curopt;
 111        }
 112
 113        gs->index++;
 114        gs->arg_index = 1;
 115
 116        if (gs->index >= argc || argv[gs->index][0] == '-') {
 117                if (!silent)
 118                        printf("option requires an argument -- %c\n", curopt);
 119                gs->opt = curopt;
 120                return ':';
 121        }
 122
 123        gs->arg = argv[gs->index++];
 124        return curopt;
 125}
 126