mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
5.8 KiB
275 lines
5.8 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* linux/lib/cmdline.c |
|
* Helper functions generally used for parsing kernel command line |
|
* and module options. |
|
* |
|
* Code and copyrights come from init/main.c and arch/i386/kernel/setup.c. |
|
* |
|
* GNU Indent formatting options for this file: -kr -i8 -npsl -pcs |
|
*/ |
|
|
|
#include <linux/export.h> |
|
#include <linux/kernel.h> |
|
#include <linux/string.h> |
|
#include <linux/ctype.h> |
|
|
|
/* |
|
* If a hyphen was found in get_option, this will handle the |
|
* range of numbers, M-N. This will expand the range and insert |
|
* the values[M, M+1, ..., N] into the ints array in get_options. |
|
*/ |
|
|
|
static int get_range(char **str, int *pint, int n) |
|
{ |
|
int x, inc_counter, upper_range; |
|
|
|
(*str)++; |
|
upper_range = simple_strtol((*str), NULL, 0); |
|
inc_counter = upper_range - *pint; |
|
for (x = *pint; n && x < upper_range; x++, n--) |
|
*pint++ = x; |
|
return inc_counter; |
|
} |
|
|
|
/** |
|
* get_option - Parse integer from an option string |
|
* @str: option string |
|
* @pint: (optional output) integer value parsed from @str |
|
* |
|
* Read an int from an option string; if available accept a subsequent |
|
* comma as well. |
|
* |
|
* When @pint is NULL the function can be used as a validator of |
|
* the current option in the string. |
|
* |
|
* Return values: |
|
* 0 - no int in string |
|
* 1 - int found, no subsequent comma |
|
* 2 - int found including a subsequent comma |
|
* 3 - hyphen found to denote a range |
|
* |
|
* Leading hyphen without integer is no integer case, but we consume it |
|
* for the sake of simplification. |
|
*/ |
|
|
|
int get_option(char **str, int *pint) |
|
{ |
|
char *cur = *str; |
|
int value; |
|
|
|
if (!cur || !(*cur)) |
|
return 0; |
|
if (*cur == '-') |
|
value = -simple_strtoull(++cur, str, 0); |
|
else |
|
value = simple_strtoull(cur, str, 0); |
|
if (pint) |
|
*pint = value; |
|
if (cur == *str) |
|
return 0; |
|
if (**str == ',') { |
|
(*str)++; |
|
return 2; |
|
} |
|
if (**str == '-') |
|
return 3; |
|
|
|
return 1; |
|
} |
|
EXPORT_SYMBOL(get_option); |
|
|
|
/** |
|
* get_options - Parse a string into a list of integers |
|
* @str: String to be parsed |
|
* @nints: size of integer array |
|
* @ints: integer array (must have room for at least one element) |
|
* |
|
* This function parses a string containing a comma-separated |
|
* list of integers, a hyphen-separated range of _positive_ integers, |
|
* or a combination of both. The parse halts when the array is |
|
* full, or when no more numbers can be retrieved from the |
|
* string. |
|
* |
|
* When @nints is 0, the function just validates the given @str and |
|
* returns the amount of parseable integers as described below. |
|
* |
|
* Returns: |
|
* |
|
* The first element is filled by the number of collected integers |
|
* in the range. The rest is what was parsed from the @str. |
|
* |
|
* Return value is the character in the string which caused |
|
* the parse to end (typically a null terminator, if @str is |
|
* completely parseable). |
|
*/ |
|
|
|
char *get_options(const char *str, int nints, int *ints) |
|
{ |
|
bool validate = (nints == 0); |
|
int res, i = 1; |
|
|
|
while (i < nints || validate) { |
|
int *pint = validate ? ints : ints + i; |
|
|
|
res = get_option((char **)&str, pint); |
|
if (res == 0) |
|
break; |
|
if (res == 3) { |
|
int n = validate ? 0 : nints - i; |
|
int range_nums; |
|
|
|
range_nums = get_range((char **)&str, pint, n); |
|
if (range_nums < 0) |
|
break; |
|
/* |
|
* Decrement the result by one to leave out the |
|
* last number in the range. The next iteration |
|
* will handle the upper number in the range |
|
*/ |
|
i += (range_nums - 1); |
|
} |
|
i++; |
|
if (res == 1) |
|
break; |
|
} |
|
ints[0] = i - 1; |
|
return (char *)str; |
|
} |
|
EXPORT_SYMBOL(get_options); |
|
|
|
/** |
|
* memparse - parse a string with mem suffixes into a number |
|
* @ptr: Where parse begins |
|
* @retptr: (output) Optional pointer to next char after parse completes |
|
* |
|
* Parses a string into a number. The number stored at @ptr is |
|
* potentially suffixed with K, M, G, T, P, E. |
|
*/ |
|
|
|
unsigned long long memparse(const char *ptr, char **retptr) |
|
{ |
|
char *endptr; /* local pointer to end of parsed string */ |
|
|
|
unsigned long long ret = simple_strtoull(ptr, &endptr, 0); |
|
|
|
switch (*endptr) { |
|
case 'E': |
|
case 'e': |
|
ret <<= 10; |
|
fallthrough; |
|
case 'P': |
|
case 'p': |
|
ret <<= 10; |
|
fallthrough; |
|
case 'T': |
|
case 't': |
|
ret <<= 10; |
|
fallthrough; |
|
case 'G': |
|
case 'g': |
|
ret <<= 10; |
|
fallthrough; |
|
case 'M': |
|
case 'm': |
|
ret <<= 10; |
|
fallthrough; |
|
case 'K': |
|
case 'k': |
|
ret <<= 10; |
|
endptr++; |
|
fallthrough; |
|
default: |
|
break; |
|
} |
|
|
|
if (retptr) |
|
*retptr = endptr; |
|
|
|
return ret; |
|
} |
|
EXPORT_SYMBOL(memparse); |
|
|
|
/** |
|
* parse_option_str - Parse a string and check an option is set or not |
|
* @str: String to be parsed |
|
* @option: option name |
|
* |
|
* This function parses a string containing a comma-separated list of |
|
* strings like a=b,c. |
|
* |
|
* Return true if there's such option in the string, or return false. |
|
*/ |
|
bool parse_option_str(const char *str, const char *option) |
|
{ |
|
while (*str) { |
|
if (!strncmp(str, option, strlen(option))) { |
|
str += strlen(option); |
|
if (!*str || *str == ',') |
|
return true; |
|
} |
|
|
|
while (*str && *str != ',') |
|
str++; |
|
|
|
if (*str == ',') |
|
str++; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
/* |
|
* Parse a string to get a param value pair. |
|
* You can use " around spaces, but can't escape ". |
|
* Hyphens and underscores equivalent in parameter names. |
|
*/ |
|
char *next_arg(char *args, char **param, char **val) |
|
{ |
|
unsigned int i, equals = 0; |
|
int in_quote = 0, quoted = 0; |
|
|
|
if (*args == '"') { |
|
args++; |
|
in_quote = 1; |
|
quoted = 1; |
|
} |
|
|
|
for (i = 0; args[i]; i++) { |
|
if (isspace(args[i]) && !in_quote) |
|
break; |
|
if (equals == 0) { |
|
if (args[i] == '=') |
|
equals = i; |
|
} |
|
if (args[i] == '"') |
|
in_quote = !in_quote; |
|
} |
|
|
|
*param = args; |
|
if (!equals) |
|
*val = NULL; |
|
else { |
|
args[equals] = '\0'; |
|
*val = args + equals + 1; |
|
|
|
/* Don't include quotes in value. */ |
|
if (**val == '"') { |
|
(*val)++; |
|
if (args[i-1] == '"') |
|
args[i-1] = '\0'; |
|
} |
|
} |
|
if (quoted && args[i-1] == '"') |
|
args[i-1] = '\0'; |
|
|
|
if (args[i]) { |
|
args[i] = '\0'; |
|
args += i + 1; |
|
} else |
|
args += i; |
|
|
|
/* Chew up trailing spaces. */ |
|
return skip_spaces(args); |
|
} |
|
EXPORT_SYMBOL(next_arg);
|
|
|