18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 28c2ecf20Sopenharmony_ci/****************************************************************************** 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Module Name: getopt 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2000 - 2020, Intel Corp. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci *****************************************************************************/ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* 118c2ecf20Sopenharmony_ci * ACPICA getopt() implementation 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Option strings: 148c2ecf20Sopenharmony_ci * "f" - Option has no arguments 158c2ecf20Sopenharmony_ci * "f:" - Option requires an argument 168c2ecf20Sopenharmony_ci * "f+" - Option has an optional argument 178c2ecf20Sopenharmony_ci * "f^" - Option has optional single-char sub-options 188c2ecf20Sopenharmony_ci * "f|" - Option has required single-char sub-options 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <acpi/acpi.h> 228c2ecf20Sopenharmony_ci#include "accommon.h" 238c2ecf20Sopenharmony_ci#include "acapps.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define ACPI_OPTION_ERROR(msg, badchar) \ 268c2ecf20Sopenharmony_ci if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciint acpi_gbl_opterr = 1; 298c2ecf20Sopenharmony_ciint acpi_gbl_optind = 1; 308c2ecf20Sopenharmony_ciint acpi_gbl_sub_opt_char = 0; 318c2ecf20Sopenharmony_cichar *acpi_gbl_optarg; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int current_char_ptr = 1; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/******************************************************************************* 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * FUNCTION: acpi_getopt_argument 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * PARAMETERS: argc, argv - from main 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * RETURN: 0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg 428c2ecf20Sopenharmony_ci * to point to the next argument. 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * DESCRIPTION: Get the next argument. Used to obtain arguments for the 458c2ecf20Sopenharmony_ci * two-character options after the original call to acpi_getopt. 468c2ecf20Sopenharmony_ci * Note: Either the argument starts at the next character after 478c2ecf20Sopenharmony_ci * the option, or it is pointed to by the next argv entry. 488c2ecf20Sopenharmony_ci * (After call to acpi_getopt, we need to backup to the previous 498c2ecf20Sopenharmony_ci * argv entry). 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci ******************************************************************************/ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciint acpi_getopt_argument(int argc, char **argv) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci acpi_gbl_optind--; 578c2ecf20Sopenharmony_ci current_char_ptr++; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 608c2ecf20Sopenharmony_ci acpi_gbl_optarg = 618c2ecf20Sopenharmony_ci &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; 628c2ecf20Sopenharmony_ci } else if (++acpi_gbl_optind >= argc) { 638c2ecf20Sopenharmony_ci ACPI_OPTION_ERROR("\nOption requires an argument", 0); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci current_char_ptr = 1; 668c2ecf20Sopenharmony_ci return (-1); 678c2ecf20Sopenharmony_ci } else { 688c2ecf20Sopenharmony_ci acpi_gbl_optarg = argv[acpi_gbl_optind++]; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci current_char_ptr = 1; 728c2ecf20Sopenharmony_ci return (0); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/******************************************************************************* 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * FUNCTION: acpi_getopt 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * PARAMETERS: argc, argv - from main 808c2ecf20Sopenharmony_ci * opts - options info list 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * RETURN: Option character or ACPI_OPT_END 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * DESCRIPTION: Get the next option 858c2ecf20Sopenharmony_ci * 868c2ecf20Sopenharmony_ci ******************************************************************************/ 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ciint acpi_getopt(int argc, char **argv, char *opts) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci int current_char; 918c2ecf20Sopenharmony_ci char *opts_ptr; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (current_char_ptr == 1) { 948c2ecf20Sopenharmony_ci if (acpi_gbl_optind >= argc || 958c2ecf20Sopenharmony_ci argv[acpi_gbl_optind][0] != '-' || 968c2ecf20Sopenharmony_ci argv[acpi_gbl_optind][1] == '\0') { 978c2ecf20Sopenharmony_ci return (ACPI_OPT_END); 988c2ecf20Sopenharmony_ci } else if (strcmp(argv[acpi_gbl_optind], "--") == 0) { 998c2ecf20Sopenharmony_ci acpi_gbl_optind++; 1008c2ecf20Sopenharmony_ci return (ACPI_OPT_END); 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* Get the option */ 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci current_char = argv[acpi_gbl_optind][current_char_ptr]; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Make sure that the option is legal */ 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (current_char == ':' || 1118c2ecf20Sopenharmony_ci (opts_ptr = strchr(opts, current_char)) == NULL) { 1128c2ecf20Sopenharmony_ci ACPI_OPTION_ERROR("Illegal option: -", current_char); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { 1158c2ecf20Sopenharmony_ci acpi_gbl_optind++; 1168c2ecf20Sopenharmony_ci current_char_ptr = 1; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci return ('?'); 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* Option requires an argument? */ 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (*++opts_ptr == ':') { 1258c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 1268c2ecf20Sopenharmony_ci acpi_gbl_optarg = 1278c2ecf20Sopenharmony_ci &argv[acpi_gbl_optind++][(int) 1288c2ecf20Sopenharmony_ci (current_char_ptr + 1)]; 1298c2ecf20Sopenharmony_ci } else if (++acpi_gbl_optind >= argc) { 1308c2ecf20Sopenharmony_ci ACPI_OPTION_ERROR("Option requires an argument: -", 1318c2ecf20Sopenharmony_ci current_char); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci current_char_ptr = 1; 1348c2ecf20Sopenharmony_ci return ('?'); 1358c2ecf20Sopenharmony_ci } else { 1368c2ecf20Sopenharmony_ci acpi_gbl_optarg = argv[acpi_gbl_optind++]; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci current_char_ptr = 1; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* Option has an optional argument? */ 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci else if (*opts_ptr == '+') { 1458c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 1468c2ecf20Sopenharmony_ci acpi_gbl_optarg = 1478c2ecf20Sopenharmony_ci &argv[acpi_gbl_optind++][(int) 1488c2ecf20Sopenharmony_ci (current_char_ptr + 1)]; 1498c2ecf20Sopenharmony_ci } else if (++acpi_gbl_optind >= argc) { 1508c2ecf20Sopenharmony_ci acpi_gbl_optarg = NULL; 1518c2ecf20Sopenharmony_ci } else { 1528c2ecf20Sopenharmony_ci acpi_gbl_optarg = argv[acpi_gbl_optind++]; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci current_char_ptr = 1; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Option has optional single-char arguments? */ 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci else if (*opts_ptr == '^') { 1618c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 1628c2ecf20Sopenharmony_ci acpi_gbl_optarg = 1638c2ecf20Sopenharmony_ci &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; 1648c2ecf20Sopenharmony_ci } else { 1658c2ecf20Sopenharmony_ci acpi_gbl_optarg = "^"; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; 1698c2ecf20Sopenharmony_ci acpi_gbl_optind++; 1708c2ecf20Sopenharmony_ci current_char_ptr = 1; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* Option has a required single-char argument? */ 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci else if (*opts_ptr == '|') { 1768c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { 1778c2ecf20Sopenharmony_ci acpi_gbl_optarg = 1788c2ecf20Sopenharmony_ci &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; 1798c2ecf20Sopenharmony_ci } else { 1808c2ecf20Sopenharmony_ci ACPI_OPTION_ERROR 1818c2ecf20Sopenharmony_ci ("Option requires a single-character suboption: -", 1828c2ecf20Sopenharmony_ci current_char); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci current_char_ptr = 1; 1858c2ecf20Sopenharmony_ci return ('?'); 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; 1898c2ecf20Sopenharmony_ci acpi_gbl_optind++; 1908c2ecf20Sopenharmony_ci current_char_ptr = 1; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* Option with no arguments */ 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci else { 1968c2ecf20Sopenharmony_ci if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { 1978c2ecf20Sopenharmony_ci current_char_ptr = 1; 1988c2ecf20Sopenharmony_ci acpi_gbl_optind++; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci acpi_gbl_optarg = NULL; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci return (current_char); 2058c2ecf20Sopenharmony_ci} 206