brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · 90ed997 Raw
276 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * linux/lib/cmdline.c4 * Helper functions generally used for parsing kernel command line5 * and module options.6 *7 * Code and copyrights come from init/main.c and arch/i386/kernel/setup.c.8 *9 * GNU Indent formatting options for this file: -kr -i8 -npsl -pcs10 */11 12#include <linux/export.h>13#include <linux/kernel.h>14#include <linux/string.h>15#include <linux/ctype.h>16 17/*18 *	If a hyphen was found in get_option, this will handle the19 *	range of numbers, M-N.  This will expand the range and insert20 *	the values[M, M+1, ..., N] into the ints array in get_options.21 */22 23static int get_range(char **str, int *pint, int n)24{25	int x, inc_counter, upper_range;26 27	(*str)++;28	upper_range = simple_strtol((*str), NULL, 0);29	inc_counter = upper_range - *pint;30	for (x = *pint; n && x < upper_range; x++, n--)31		*pint++ = x;32	return inc_counter;33}34 35/**36 *	get_option - Parse integer from an option string37 *	@str: option string38 *	@pint: (optional output) integer value parsed from @str39 *40 *	Read an int from an option string; if available accept a subsequent41 *	comma as well.42 *43 *	When @pint is NULL the function can be used as a validator of44 *	the current option in the string.45 *46 *	Return values:47 *	0 - no int in string48 *	1 - int found, no subsequent comma49 *	2 - int found including a subsequent comma50 *	3 - hyphen found to denote a range51 *52 *	Leading hyphen without integer is no integer case, but we consume it53 *	for the sake of simplification.54 */55 56int get_option(char **str, int *pint)57{58	char *cur = *str;59	int value;60 61	if (!cur || !(*cur))62		return 0;63	if (*cur == '-')64		value = -simple_strtoull(++cur, str, 0);65	else66		value = simple_strtoull(cur, str, 0);67	if (pint)68		*pint = value;69	if (cur == *str)70		return 0;71	if (**str == ',') {72		(*str)++;73		return 2;74	}75	if (**str == '-')76		return 3;77 78	return 1;79}80EXPORT_SYMBOL(get_option);81 82/**83 *	get_options - Parse a string into a list of integers84 *	@str: String to be parsed85 *	@nints: size of integer array86 *	@ints: integer array (must have room for at least one element)87 *88 *	This function parses a string containing a comma-separated89 *	list of integers, a hyphen-separated range of _positive_ integers,90 *	or a combination of both.  The parse halts when the array is91 *	full, or when no more numbers can be retrieved from the92 *	string.93 *94 *	When @nints is 0, the function just validates the given @str and95 *	returns the amount of parseable integers as described below.96 *97 *	Returns:98 *99 *	The first element is filled by the number of collected integers100 *	in the range. The rest is what was parsed from the @str.101 *102 *	Return value is the character in the string which caused103 *	the parse to end (typically a null terminator, if @str is104 *	completely parseable).105 */106 107char *get_options(const char *str, int nints, int *ints)108{109	bool validate = (nints == 0);110	int res, i = 1;111 112	while (i < nints || validate) {113		int *pint = validate ? ints : ints + i;114 115		res = get_option((char **)&str, pint);116		if (res == 0)117			break;118		if (res == 3) {119			int n = validate ? 0 : nints - i;120			int range_nums;121 122			range_nums = get_range((char **)&str, pint, n);123			if (range_nums < 0)124				break;125			/*126			 * Decrement the result by one to leave out the127			 * last number in the range.  The next iteration128			 * will handle the upper number in the range129			 */130			i += (range_nums - 1);131		}132		i++;133		if (res == 1)134			break;135	}136	ints[0] = i - 1;137	return (char *)str;138}139EXPORT_SYMBOL(get_options);140 141/**142 *	memparse - parse a string with mem suffixes into a number143 *	@ptr: Where parse begins144 *	@retptr: (output) Optional pointer to next char after parse completes145 *146 *	Parses a string into a number.  The number stored at @ptr is147 *	potentially suffixed with K, M, G, T, P, E.148 */149 150unsigned long long memparse(const char *ptr, char **retptr)151{152	char *endptr;	/* local pointer to end of parsed string */153 154	unsigned long long ret = simple_strtoull(ptr, &endptr, 0);155 156	switch (*endptr) {157	case 'E':158	case 'e':159		ret <<= 10;160		fallthrough;161	case 'P':162	case 'p':163		ret <<= 10;164		fallthrough;165	case 'T':166	case 't':167		ret <<= 10;168		fallthrough;169	case 'G':170	case 'g':171		ret <<= 10;172		fallthrough;173	case 'M':174	case 'm':175		ret <<= 10;176		fallthrough;177	case 'K':178	case 'k':179		ret <<= 10;180		endptr++;181		fallthrough;182	default:183		break;184	}185 186	if (retptr)187		*retptr = endptr;188 189	return ret;190}191EXPORT_SYMBOL(memparse);192 193/**194 *	parse_option_str - Parse a string and check an option is set or not195 *	@str: String to be parsed196 *	@option: option name197 *198 *	This function parses a string containing a comma-separated list of199 *	strings like a=b,c.200 *201 *	Return true if there's such option in the string, or return false.202 */203bool parse_option_str(const char *str, const char *option)204{205	while (*str) {206		if (!strncmp(str, option, strlen(option))) {207			str += strlen(option);208			if (!*str || *str == ',')209				return true;210		}211 212		while (*str && *str != ',')213			str++;214 215		if (*str == ',')216			str++;217	}218 219	return false;220}221 222/*223 * Parse a string to get a param value pair.224 * You can use " around spaces, but can't escape ".225 * Hyphens and underscores equivalent in parameter names.226 */227char *next_arg(char *args, char **param, char **val)228{229	unsigned int i, equals = 0;230	int in_quote = 0, quoted = 0;231 232	if (*args == '"') {233		args++;234		in_quote = 1;235		quoted = 1;236	}237 238	for (i = 0; args[i]; i++) {239		if (isspace(args[i]) && !in_quote)240			break;241		if (equals == 0) {242			if (args[i] == '=')243				equals = i;244		}245		if (args[i] == '"')246			in_quote = !in_quote;247	}248 249	*param = args;250	if (!equals)251		*val = NULL;252	else {253		args[equals] = '\0';254		*val = args + equals + 1;255 256		/* Don't include quotes in value. */257		if (**val == '"') {258			(*val)++;259			if (args[i-1] == '"')260				args[i-1] = '\0';261		}262	}263	if (quoted && i > 0 && args[i-1] == '"')264		args[i-1] = '\0';265 266	if (args[i]) {267		args[i] = '\0';268		args += i + 1;269	} else270		args += i;271 272	/* Chew up trailing spaces. */273	return skip_spaces(args);274}275EXPORT_SYMBOL(next_arg);276