162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: getopt 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * ACPICA getopt() implementation 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Option strings: 1462306a36Sopenharmony_ci * "f" - Option has no arguments 1562306a36Sopenharmony_ci * "f:" - Option requires an argument 1662306a36Sopenharmony_ci * "f+" - Option has an optional argument 1762306a36Sopenharmony_ci * "f^" - Option has optional single-char sub-options 1862306a36Sopenharmony_ci * "f|" - Option has required single-char sub-options 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <acpi/acpi.h> 2262306a36Sopenharmony_ci#include "accommon.h" 2362306a36Sopenharmony_ci#include "acapps.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define ACPI_OPTION_ERROR(msg, badchar) \ 2662306a36Sopenharmony_ci if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciint acpi_gbl_opterr = 1; 2962306a36Sopenharmony_ciint acpi_gbl_optind = 1; 3062306a36Sopenharmony_ciint acpi_gbl_sub_opt_char = 0; 3162306a36Sopenharmony_cichar *acpi_gbl_optarg; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic int current_char_ptr = 1; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/******************************************************************************* 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * FUNCTION: acpi_getopt_argument 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * PARAMETERS: argc, argv - from main 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * RETURN: 0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg 4262306a36Sopenharmony_ci * to point to the next argument. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * DESCRIPTION: Get the next argument. Used to obtain arguments for the 4562306a36Sopenharmony_ci * two-character options after the original call to acpi_getopt. 4662306a36Sopenharmony_ci * Note: Either the argument starts at the next character after 4762306a36Sopenharmony_ci * the option, or it is pointed to by the next argv entry. 4862306a36Sopenharmony_ci * (After call to acpi_getopt, we need to backup to the previous 4962306a36Sopenharmony_ci * argv entry). 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci ******************************************************************************/ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciint acpi_getopt_argument(int argc, char **argv) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci acpi_gbl_optind--; 5762306a36Sopenharmony_ci current_char_ptr++; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 6062306a36Sopenharmony_ci acpi_gbl_optarg = 6162306a36Sopenharmony_ci &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; 6262306a36Sopenharmony_ci } else if (++acpi_gbl_optind >= argc) { 6362306a36Sopenharmony_ci ACPI_OPTION_ERROR("\nOption requires an argument", 0); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci current_char_ptr = 1; 6662306a36Sopenharmony_ci return (-1); 6762306a36Sopenharmony_ci } else { 6862306a36Sopenharmony_ci acpi_gbl_optarg = argv[acpi_gbl_optind++]; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci current_char_ptr = 1; 7262306a36Sopenharmony_ci return (0); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/******************************************************************************* 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * FUNCTION: acpi_getopt 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * PARAMETERS: argc, argv - from main 8062306a36Sopenharmony_ci * opts - options info list 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * RETURN: Option character or ACPI_OPT_END 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * DESCRIPTION: Get the next option 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci ******************************************************************************/ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciint acpi_getopt(int argc, char **argv, char *opts) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci int current_char; 9162306a36Sopenharmony_ci char *opts_ptr; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (current_char_ptr == 1) { 9462306a36Sopenharmony_ci if (acpi_gbl_optind >= argc || 9562306a36Sopenharmony_ci argv[acpi_gbl_optind][0] != '-' || 9662306a36Sopenharmony_ci argv[acpi_gbl_optind][1] == '\0') { 9762306a36Sopenharmony_ci return (ACPI_OPT_END); 9862306a36Sopenharmony_ci } else if (strcmp(argv[acpi_gbl_optind], "--") == 0) { 9962306a36Sopenharmony_ci acpi_gbl_optind++; 10062306a36Sopenharmony_ci return (ACPI_OPT_END); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Get the option */ 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci current_char = argv[acpi_gbl_optind][current_char_ptr]; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* Make sure that the option is legal */ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (current_char == ':' || 11162306a36Sopenharmony_ci (opts_ptr = strchr(opts, current_char)) == NULL) { 11262306a36Sopenharmony_ci ACPI_OPTION_ERROR("Illegal option: -", current_char); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { 11562306a36Sopenharmony_ci acpi_gbl_optind++; 11662306a36Sopenharmony_ci current_char_ptr = 1; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return ('?'); 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* Option requires an argument? */ 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (*++opts_ptr == ':') { 12562306a36Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 12662306a36Sopenharmony_ci acpi_gbl_optarg = 12762306a36Sopenharmony_ci &argv[acpi_gbl_optind++][(int) 12862306a36Sopenharmony_ci (current_char_ptr + 1)]; 12962306a36Sopenharmony_ci } else if (++acpi_gbl_optind >= argc) { 13062306a36Sopenharmony_ci ACPI_OPTION_ERROR("Option requires an argument: -", 13162306a36Sopenharmony_ci current_char); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci current_char_ptr = 1; 13462306a36Sopenharmony_ci return ('?'); 13562306a36Sopenharmony_ci } else { 13662306a36Sopenharmony_ci acpi_gbl_optarg = argv[acpi_gbl_optind++]; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci current_char_ptr = 1; 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* Option has an optional argument? */ 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci else if (*opts_ptr == '+') { 14562306a36Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 14662306a36Sopenharmony_ci acpi_gbl_optarg = 14762306a36Sopenharmony_ci &argv[acpi_gbl_optind++][(int) 14862306a36Sopenharmony_ci (current_char_ptr + 1)]; 14962306a36Sopenharmony_ci } else if (++acpi_gbl_optind >= argc) { 15062306a36Sopenharmony_ci acpi_gbl_optarg = NULL; 15162306a36Sopenharmony_ci } else { 15262306a36Sopenharmony_ci acpi_gbl_optarg = argv[acpi_gbl_optind++]; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci current_char_ptr = 1; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* Option has optional single-char arguments? */ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci else if (*opts_ptr == '^') { 16162306a36Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 16262306a36Sopenharmony_ci acpi_gbl_optarg = 16362306a36Sopenharmony_ci &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; 16462306a36Sopenharmony_ci } else { 16562306a36Sopenharmony_ci acpi_gbl_optarg = "^"; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; 16962306a36Sopenharmony_ci acpi_gbl_optind++; 17062306a36Sopenharmony_ci current_char_ptr = 1; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* Option has a required single-char argument? */ 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci else if (*opts_ptr == '|') { 17662306a36Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 17762306a36Sopenharmony_ci acpi_gbl_optarg = 17862306a36Sopenharmony_ci &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; 17962306a36Sopenharmony_ci } else { 18062306a36Sopenharmony_ci ACPI_OPTION_ERROR 18162306a36Sopenharmony_ci ("Option requires a single-character suboption: -", 18262306a36Sopenharmony_ci current_char); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci current_char_ptr = 1; 18562306a36Sopenharmony_ci return ('?'); 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; 18962306a36Sopenharmony_ci acpi_gbl_optind++; 19062306a36Sopenharmony_ci current_char_ptr = 1; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* Option with no arguments */ 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci else { 19662306a36Sopenharmony_ci if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { 19762306a36Sopenharmony_ci current_char_ptr = 1; 19862306a36Sopenharmony_ci acpi_gbl_optind++; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci acpi_gbl_optarg = NULL; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci return (current_char); 20562306a36Sopenharmony_ci} 206