linux-stable/lib/cmdline.c
Derek Fults 22f2e28017 [PATCH] get_options to allow a hypenated range for isolcpus
This allows a hyphenated range of positive numbers in the string passed
to command line helper function, get_options.

Currently the command line option "isolcpus=" takes as its argument a
list of cpus.

Format: <cpu number>,...,<cpu number>
Valid values of <cpu_number>  include all cpus, 0 to "number of CPUs in
system - 1". This can get extremely long when isolating the majority of
cpus on a large system.  The kernel isolcpus code would not need any
changing to use this feature.  To use it, the change would be in the
command line format for 'isolcpus='
Format:
<cpu number>,...,<cpu number>
or
<cpu number>-<cpu number>  (must be a positive range in ascending
order.)
or a mixture
<cpu number>,...,<cpu number>-<cpu number>

Signed-off-by: Derek Fults <dfults@sgi.com>
Cc: "Randy.Dunlap" <rdunlap@xenotime.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 08:39:35 -08:00

153 lines
3.5 KiB
C

/*
* 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.
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*
* GNU Indent formatting options for this file: -kr -i8 -npsl -pcs
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.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 x, inc_counter, upper_range;
(*str)++;
upper_range = simple_strtol((*str), NULL, 0);
inc_counter = upper_range - *pint;
for (x = *pint; x < upper_range; x++)
*pint++ = x;
return inc_counter;
}
/**
* get_option - Parse integer from an option string
* @str: option string
* @pint: (output) integer value parsed from @str
*
* Read an int from an option string; if available accept a subsequent
* comma as well.
*
* 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
*/
int get_option (char **str, int *pint)
{
char *cur = *str;
if (!cur || !(*cur))
return 0;
*pint = simple_strtol (cur, str, 0);
if (cur == *str)
return 0;
if (**str == ',') {
(*str)++;
return 2;
}
if (**str == '-')
return 3;
return 1;
}
/**
* get_options - Parse a string into a list of integers
* @str: String to be parsed
* @nints: size of integer array
* @ints: integer array
*
* 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.
*
* 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)
{
int res, i = 1;
while (i < nints) {
res = get_option ((char **)&str, ints + i);
if (res == 0)
break;
if (res == 3) {
int range_nums;
range_nums = get_range((char **)&str, ints + i);
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;
}
/**
* memparse - parse a string with mem suffixes into a number
* @ptr: Where parse begins
* @retptr: (output) Pointer to next char after parse completes
*
* Parses a string into a number. The number stored at @ptr is
* potentially suffixed with %K (for kilobytes, or 1024 bytes),
* %M (for megabytes, or 1048576 bytes), or %G (for gigabytes, or
* 1073741824). If the number is suffixed with K, M, or G, then
* the return value is the number multiplied by one kilobyte, one
* megabyte, or one gigabyte, respectively.
*/
unsigned long long memparse (char *ptr, char **retptr)
{
unsigned long long ret = simple_strtoull (ptr, retptr, 0);
switch (**retptr) {
case 'G':
case 'g':
ret <<= 10;
case 'M':
case 'm':
ret <<= 10;
case 'K':
case 'k':
ret <<= 10;
(*retptr)++;
default:
break;
}
return ret;
}
EXPORT_SYMBOL(memparse);
EXPORT_SYMBOL(get_option);
EXPORT_SYMBOL(get_options);