Blame bitmap.c

Packit 9eaa09
/*
Packit 9eaa09
Packit 9eaa09
This file is taken from the Linux kernel and minimally adapted for use in userspace
Packit 9eaa09
Packit 9eaa09
*/
Packit 9eaa09
Packit 9eaa09
/*
Packit 9eaa09
 * lib/bitmap.c
Packit 9eaa09
 * Helper functions for bitmap.h.
Packit 9eaa09
 *
Packit 9eaa09
 * This source code is licensed under the GNU General Public License,
Packit 9eaa09
 * Version 2.  See the file COPYING for more details.
Packit 9eaa09
 */
Packit 9eaa09
#include "config.h"
Packit 9eaa09
#include <unistd.h>
Packit 9eaa09
#include <errno.h>
Packit 9eaa09
#include <stdio.h>
Packit 9eaa09
#include <stdlib.h>
Packit 9eaa09
#include <ctype.h>
Packit 9eaa09
#include "bitmap.h"
Packit 9eaa09
#include "non-atomic.h"
Packit 9eaa09
Packit 9eaa09
/*
Packit 9eaa09
 * bitmaps provide an array of bits, implemented using an an
Packit 9eaa09
 * array of unsigned longs.  The number of valid bits in a
Packit 9eaa09
 * given bitmap does _not_ need to be an exact multiple of
Packit 9eaa09
 * BITS_PER_LONG.
Packit 9eaa09
 *
Packit 9eaa09
 * The possible unused bits in the last, partially used word
Packit 9eaa09
 * of a bitmap are 'don't care'.  The implementation makes
Packit 9eaa09
 * no particular effort to keep them zero.  It ensures that
Packit 9eaa09
 * their value will not affect the results of any operation.
Packit 9eaa09
 * The bitmap operations that return Boolean (bitmap_empty,
Packit 9eaa09
 * for example) or scalar (bitmap_weight, for example) results
Packit 9eaa09
 * carefully filter out these unused bits from impacting their
Packit 9eaa09
 * results.
Packit 9eaa09
 *
Packit 9eaa09
 * These operations actually hold to a slightly stronger rule:
Packit 9eaa09
 * if you don't input any bitmaps to these ops that have some
Packit 9eaa09
 * unused bits set, then they won't output any set unused bits
Packit 9eaa09
 * in output bitmaps.
Packit 9eaa09
 *
Packit 9eaa09
 * The byte ordering of bitmaps is more natural on little
Packit 9eaa09
 * endian architectures.  See the big-endian headers
Packit 9eaa09
 * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
Packit 9eaa09
 * for the best explanations of this ordering.
Packit 9eaa09
 */
Packit 9eaa09
Packit 9eaa09
int __bitmap_empty(const unsigned long *bitmap, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = bits/BITS_PER_LONG;
Packit 9eaa09
	for (k = 0; k < lim; ++k)
Packit 9eaa09
		if (bitmap[k])
Packit 9eaa09
			return 0;
Packit 9eaa09
Packit 9eaa09
	if (bits % BITS_PER_LONG)
Packit 9eaa09
		if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
Packit 9eaa09
			return 0;
Packit 9eaa09
Packit 9eaa09
	return 1;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
int __bitmap_full(const unsigned long *bitmap, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = bits/BITS_PER_LONG;
Packit 9eaa09
	for (k = 0; k < lim; ++k)
Packit 9eaa09
		if (~bitmap[k])
Packit 9eaa09
			return 0;
Packit 9eaa09
Packit 9eaa09
	if (bits % BITS_PER_LONG)
Packit 9eaa09
		if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
Packit 9eaa09
			return 0;
Packit 9eaa09
Packit 9eaa09
	return 1;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
int __bitmap_weight(const unsigned long *bitmap, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, w = 0, lim = bits/BITS_PER_LONG;
Packit 9eaa09
Packit 9eaa09
	for (k = 0; k < lim; k++)
Packit 9eaa09
		w += hweight_long(bitmap[k]);
Packit 9eaa09
Packit 9eaa09
	if (bits % BITS_PER_LONG)
Packit 9eaa09
		w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
Packit 9eaa09
Packit 9eaa09
	return w;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
int __bitmap_equal(const unsigned long *bitmap1,
Packit 9eaa09
		const unsigned long *bitmap2, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = bits/BITS_PER_LONG;
Packit 9eaa09
	for (k = 0; k < lim; ++k)
Packit 9eaa09
		if (bitmap1[k] != bitmap2[k])
Packit 9eaa09
			return 0;
Packit 9eaa09
Packit 9eaa09
	if (bits % BITS_PER_LONG)
Packit 9eaa09
		if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
Packit 9eaa09
			return 0;
Packit 9eaa09
Packit 9eaa09
	return 1;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = bits/BITS_PER_LONG;
Packit 9eaa09
	for (k = 0; k < lim; ++k)
Packit 9eaa09
		dst[k] = ~src[k];
Packit 9eaa09
Packit 9eaa09
	if (bits % BITS_PER_LONG)
Packit 9eaa09
		dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
/*
Packit 9eaa09
 * __bitmap_shift_right - logical right shift of the bits in a bitmap
Packit 9eaa09
 *   @dst - destination bitmap
Packit 9eaa09
 *   @src - source bitmap
Packit 9eaa09
 *   @nbits - shift by this many bits
Packit 9eaa09
 *   @bits - bitmap size, in bits
Packit 9eaa09
 *
Packit 9eaa09
 * Shifting right (dividing) means moving bits in the MS -> LS bit
Packit 9eaa09
 * direction.  Zeros are fed into the vacated MS positions and the
Packit 9eaa09
 * LS bits shifted off the bottom are lost.
Packit 9eaa09
 */
Packit 9eaa09
void __bitmap_shift_right(unsigned long *dst,
Packit 9eaa09
			const unsigned long *src, int shift, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
Packit 9eaa09
	int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
Packit 9eaa09
	unsigned long mask = (1UL << left) - 1;
Packit 9eaa09
	for (k = 0; off + k < lim; ++k) {
Packit 9eaa09
		unsigned long upper, lower;
Packit 9eaa09
Packit 9eaa09
		/*
Packit 9eaa09
		 * If shift is not word aligned, take lower rem bits of
Packit 9eaa09
		 * word above and make them the top rem bits of result.
Packit 9eaa09
		 */
Packit 9eaa09
		if (!rem || off + k + 1 >= lim)
Packit 9eaa09
			upper = 0;
Packit 9eaa09
		else {
Packit 9eaa09
			upper = src[off + k + 1];
Packit 9eaa09
			if (off + k + 1 == lim - 1 && left)
Packit 9eaa09
				upper &= mask;
Packit 9eaa09
		}
Packit 9eaa09
		lower = src[off + k];
Packit 9eaa09
		if (left && off + k == lim - 1)
Packit 9eaa09
			lower &= mask;
Packit 9eaa09
		dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
Packit 9eaa09
		if (left && k == lim - 1)
Packit 9eaa09
			dst[k] &= mask;
Packit 9eaa09
	}
Packit 9eaa09
	if (off)
Packit 9eaa09
		memset(&dst[lim - off], 0, off*sizeof(unsigned long));
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
Packit 9eaa09
/*
Packit 9eaa09
 * __bitmap_shift_left - logical left shift of the bits in a bitmap
Packit 9eaa09
 *   @dst - destination bitmap
Packit 9eaa09
 *   @src - source bitmap
Packit 9eaa09
 *   @nbits - shift by this many bits
Packit 9eaa09
 *   @bits - bitmap size, in bits
Packit 9eaa09
 *
Packit 9eaa09
 * Shifting left (multiplying) means moving bits in the LS -> MS
Packit 9eaa09
 * direction.  Zeros are fed into the vacated LS bit positions
Packit 9eaa09
 * and those MS bits shifted off the top are lost.
Packit 9eaa09
 */
Packit 9eaa09
Packit 9eaa09
void __bitmap_shift_left(unsigned long *dst,
Packit 9eaa09
			const unsigned long *src, int shift, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
Packit 9eaa09
	int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
Packit 9eaa09
	for (k = lim - off - 1; k >= 0; --k) {
Packit 9eaa09
		unsigned long upper, lower;
Packit 9eaa09
Packit 9eaa09
		/*
Packit 9eaa09
		 * If shift is not word aligned, take upper rem bits of
Packit 9eaa09
		 * word below and make them the bottom rem bits of result.
Packit 9eaa09
		 */
Packit 9eaa09
		if (rem && k > 0)
Packit 9eaa09
			lower = src[k - 1];
Packit 9eaa09
		else
Packit 9eaa09
			lower = 0;
Packit 9eaa09
		upper = src[k];
Packit 9eaa09
		if (left && k == lim - 1)
Packit 9eaa09
			upper &= (1UL << left) - 1;
Packit 9eaa09
		dst[k + off] = lower  >> (BITS_PER_LONG - rem) | upper << rem;
Packit 9eaa09
		if (left && k + off == lim - 1)
Packit 9eaa09
			dst[k + off] &= (1UL << left) - 1;
Packit 9eaa09
	}
Packit 9eaa09
	if (off)
Packit 9eaa09
		memset(dst, 0, off*sizeof(unsigned long));
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
Packit 9eaa09
				const unsigned long *bitmap2, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k;
Packit 9eaa09
	int nr = BITS_TO_LONGS(bits);
Packit 9eaa09
Packit 9eaa09
	for (k = 0; k < nr; k++)
Packit 9eaa09
		dst[k] = bitmap1[k] & bitmap2[k];
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
Packit 9eaa09
				const unsigned long *bitmap2, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k;
Packit 9eaa09
	int nr = BITS_TO_LONGS(bits);
Packit 9eaa09
Packit 9eaa09
	for (k = 0; k < nr; k++)
Packit 9eaa09
		dst[k] = bitmap1[k] | bitmap2[k];
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
Packit 9eaa09
				const unsigned long *bitmap2, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k;
Packit 9eaa09
	int nr = BITS_TO_LONGS(bits);
Packit 9eaa09
Packit 9eaa09
	for (k = 0; k < nr; k++)
Packit 9eaa09
		dst[k] = bitmap1[k] ^ bitmap2[k];
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
Packit 9eaa09
				const unsigned long *bitmap2, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k;
Packit 9eaa09
	int nr = BITS_TO_LONGS(bits);
Packit 9eaa09
Packit 9eaa09
	for (k = 0; k < nr; k++)
Packit 9eaa09
		dst[k] = bitmap1[k] & ~bitmap2[k];
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
int __bitmap_intersects(const unsigned long *bitmap1,
Packit 9eaa09
				const unsigned long *bitmap2, int bits)
Packit 9eaa09
{
Packit 9eaa09
	int k, lim = bits/BITS_PER_LONG;
Packit 9eaa09
	for (k = 0; k < lim; ++k)
Packit 9eaa09
		if (bitmap1[k] & bitmap2[k])
Packit 9eaa09
			return 1;
Packit 9eaa09
Packit 9eaa09
	if (bits % BITS_PER_LONG)
Packit 9eaa09
		if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
Packit 9eaa09
			return 1;
Packit 9eaa09
	return 0;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
/*
Packit 9eaa09
 * Bitmap printing & parsing functions: first version by Bill Irwin,
Packit 9eaa09
 * second version by Paul Jackson, third by Joe Korty.
Packit 9eaa09
 */
Packit 9eaa09
Packit 9eaa09
#define CHUNKSZ				32
Packit 9eaa09
#define nbits_to_hold_value(val)	fls(val)
Packit 9eaa09
#define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
Packit 9eaa09
#define BASEDEC 10		/* fancier cpuset lists input in decimal */
Packit 9eaa09
Packit 9eaa09
/**
Packit 9eaa09
 * bitmap_scnprintf - convert bitmap to an ASCII hex string.
Packit 9eaa09
 * @buf: byte buffer into which string is placed
Packit 9eaa09
 * @buflen: reserved size of @buf, in bytes
Packit 9eaa09
 * @maskp: pointer to bitmap to convert
Packit 9eaa09
 * @nmaskbits: size of bitmap, in bits
Packit 9eaa09
 *
Packit 9eaa09
 * Exactly @nmaskbits bits are displayed.  Hex digits are grouped into
Packit 9eaa09
 * comma-separated sets of eight digits per set.
Packit 9eaa09
 */
Packit 9eaa09
int bitmap_scnprintf(char *buf, unsigned int buflen,
Packit 9eaa09
	const unsigned long *maskp, int nmaskbits)
Packit 9eaa09
{
Packit 9eaa09
	int i, word, bit, len = 0;
Packit 9eaa09
	unsigned long val;
Packit 9eaa09
	const char *sep = "";
Packit 9eaa09
	int chunksz;
Packit 9eaa09
	uint32_t chunkmask;
Packit 9eaa09
	int first = 1;
Packit 9eaa09
Packit 9eaa09
	chunksz = nmaskbits & (CHUNKSZ - 1);
Packit 9eaa09
	if (chunksz == 0)
Packit 9eaa09
		chunksz = CHUNKSZ;
Packit 9eaa09
Packit 9eaa09
	i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
Packit 9eaa09
	for (; i >= 0; i -= CHUNKSZ) {
Packit 9eaa09
		chunkmask = ((1ULL << chunksz) - 1);
Packit 9eaa09
		word = i / BITS_PER_LONG;
Packit 9eaa09
		bit = i % BITS_PER_LONG;
Packit 9eaa09
		val = (maskp[word] >> bit) & chunkmask;
Packit 9eaa09
		if (val!=0 || !first || i==0)  {
Packit 9eaa09
			len += snprintf(buf+len, buflen-len, "%s%0*lx", sep,
Packit 9eaa09
				(chunksz+3)/4, val);
Packit 9eaa09
			sep = ",";
Packit 9eaa09
			first = 0;
Packit 9eaa09
		}
Packit 9eaa09
		chunksz = CHUNKSZ;
Packit 9eaa09
	}
Packit 9eaa09
	return len;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
/**
Packit 9eaa09
 * __bitmap_parse - convert an ASCII hex string into a bitmap.
Packit 9eaa09
 * @buf: pointer to buffer containing string.
Packit 9eaa09
 * @buflen: buffer size in bytes.  If string is smaller than this
Packit 9eaa09
 *    then it must be terminated with a \0.
Packit 9eaa09
 * @is_user: location of buffer, 0 indicates kernel space
Packit 9eaa09
 * @maskp: pointer to bitmap array that will contain result.
Packit 9eaa09
 * @nmaskbits: size of bitmap, in bits.
Packit 9eaa09
 *
Packit 9eaa09
 * Commas group hex digits into chunks.  Each chunk defines exactly 32
Packit 9eaa09
 * bits of the resultant bitmask.  No chunk may specify a value larger
Packit 9eaa09
 * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
Packit 9eaa09
 * then leading 0-bits are prepended.  %-EINVAL is returned for illegal
Packit 9eaa09
 * characters and for grouping errors such as "1,,5", ",44", "," and "".
Packit 9eaa09
 * Leading and trailing whitespace accepted, but not embedded whitespace.
Packit 9eaa09
 */
Packit 9eaa09
int __bitmap_parse(const char *buf, unsigned int buflen,
Packit 9eaa09
		int is_user __attribute((unused)), unsigned long *maskp,
Packit 9eaa09
		int nmaskbits)
Packit 9eaa09
{
Packit 9eaa09
	int c, old_c, totaldigits, ndigits, nchunks, nbits;
Packit 9eaa09
	uint32_t chunk;
Packit 9eaa09
Packit 9eaa09
	bitmap_zero(maskp, nmaskbits);
Packit 9eaa09
Packit 9eaa09
	nchunks = nbits = totaldigits = c = 0;
Packit 9eaa09
	do {
Packit 9eaa09
		chunk = ndigits = 0;
Packit 9eaa09
Packit 9eaa09
		/* Get the next chunk of the bitmap */
Packit 9eaa09
		while (buflen) {
Packit 9eaa09
			old_c = c;
Packit 9eaa09
			c = *buf++;
Packit 9eaa09
			buflen--;
Packit 9eaa09
			if (isspace(c))
Packit 9eaa09
				continue;
Packit 9eaa09
Packit 9eaa09
			/*
Packit 9eaa09
			 * If the last character was a space and the current
Packit 9eaa09
			 * character isn't '\0', we've got embedded whitespace.
Packit 9eaa09
			 * This is a no-no, so throw an error.
Packit 9eaa09
			 */
Packit 9eaa09
			if (totaldigits && c && isspace(old_c))
Packit 9eaa09
				return 0;
Packit 9eaa09
Packit 9eaa09
			/* A '\0' or a ',' signal the end of the chunk */
Packit 9eaa09
			if (c == '\0' || c == ',')
Packit 9eaa09
				break;
Packit 9eaa09
Packit 9eaa09
			if (!isxdigit(c))
Packit 9eaa09
				return -EINVAL;
Packit 9eaa09
Packit 9eaa09
			/*
Packit 9eaa09
			 * Make sure there are at least 4 free bits in 'chunk'.
Packit 9eaa09
			 * If not, this hexdigit will overflow 'chunk', so
Packit 9eaa09
			 * throw an error.
Packit 9eaa09
			 */
Packit 9eaa09
			if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
Packit 9eaa09
				return -EOVERFLOW;
Packit 9eaa09
Packit 9eaa09
			chunk = (chunk << 4) | unhex(c);
Packit 9eaa09
			ndigits++; totaldigits++;
Packit 9eaa09
		}
Packit 9eaa09
		if (ndigits == 0)
Packit 9eaa09
			return -EINVAL;
Packit 9eaa09
		if (nchunks == 0 && chunk == 0)
Packit 9eaa09
			continue;
Packit 9eaa09
Packit 9eaa09
		__bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
Packit 9eaa09
		*maskp |= chunk;
Packit 9eaa09
		nchunks++;
Packit 9eaa09
		nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
Packit 9eaa09
		if (nbits > nmaskbits)
Packit 9eaa09
			return -EOVERFLOW;
Packit 9eaa09
	} while (buflen && c == ',');
Packit 9eaa09
Packit 9eaa09
	return 0;
Packit 9eaa09
}
Packit 9eaa09
Packit 9eaa09
/**
Packit 9eaa09
 * __bitmap_parselist - convert list format ASCII string to bitmap
Packit 9eaa09
 * @buf: read nul-terminated user string from this buffer
Packit 9eaa09
 * @buflen: buffer size in bytes.  If string is smaller than this
Packit 9eaa09
 *    then it must be terminated with a \0.
Packit 9eaa09
 * @is_user: location of buffer, 0 indicates kernel space
Packit 9eaa09
 * @maskp: write resulting mask here
Packit 9eaa09
 * @nmaskbits: number of bits in mask to be written
Packit 9eaa09
 *
Packit 9eaa09
 * Input format is a comma-separated list of decimal numbers and
Packit 9eaa09
 * ranges.  Consecutively set bits are shown as two hyphen-separated
Packit 9eaa09
 * decimal numbers, the smallest and largest bit numbers set in
Packit 9eaa09
 * the range.
Packit 9eaa09
 *
Packit 9eaa09
 * Returns 0 on success, -errno on invalid input strings.
Packit 9eaa09
 * Error values:
Packit 9eaa09
 *    %-EINVAL: second number in range smaller than first
Packit 9eaa09
 *    %-EINVAL: invalid character in string
Packit 9eaa09
 *    %-ERANGE: bit number specified too large for mask
Packit 9eaa09
 */
Packit 9eaa09
int __bitmap_parselist(const char *buf, unsigned int buflen,
Packit 9eaa09
		int is_user __attribute((unused)), unsigned long *maskp,
Packit 9eaa09
		int nmaskbits)
Packit 9eaa09
{
Packit 9eaa09
	int a, b, c, old_c, totaldigits;
Packit 9eaa09
	int exp_digit, in_range;
Packit 9eaa09
Packit 9eaa09
	totaldigits = c = 0;
Packit 9eaa09
	bitmap_zero(maskp, nmaskbits);
Packit 9eaa09
	do {
Packit 9eaa09
		exp_digit = 1;
Packit 9eaa09
		in_range = 0;
Packit 9eaa09
		a = b = 0;
Packit 9eaa09
Packit 9eaa09
		/* Get the next cpu# or a range of cpu#'s */
Packit 9eaa09
		while (buflen) {
Packit 9eaa09
			old_c = c;
Packit 9eaa09
			c = *buf++;
Packit 9eaa09
			buflen--;
Packit 9eaa09
			if (isspace(c))
Packit 9eaa09
				continue;
Packit 9eaa09
Packit 9eaa09
			/*
Packit 9eaa09
			 * If the last character was a space and the current
Packit 9eaa09
			 * character isn't '\0', we've got embedded whitespace.
Packit 9eaa09
			 * This is a no-no, so throw an error.
Packit 9eaa09
			 */
Packit 9eaa09
			if (totaldigits && c && isspace(old_c))
Packit 9eaa09
				return -EINVAL;
Packit 9eaa09
Packit 9eaa09
			/* A '\0' or a ',' signal the end of a cpu# or range */
Packit 9eaa09
			if (c == '\0' || c == ',')
Packit 9eaa09
				break;
Packit 9eaa09
Packit 9eaa09
			if (c == '-') {
Packit 9eaa09
				if (exp_digit || in_range)
Packit 9eaa09
					return -EINVAL;
Packit 9eaa09
				b = 0;
Packit 9eaa09
				in_range = 1;
Packit 9eaa09
				exp_digit = 1;
Packit 9eaa09
				continue;
Packit 9eaa09
			}
Packit 9eaa09
Packit 9eaa09
			if (!isdigit(c))
Packit 9eaa09
				return -EINVAL;
Packit 9eaa09
Packit 9eaa09
			b = b * 10 + (c - '0');
Packit 9eaa09
			if (!in_range)
Packit 9eaa09
				a = b;
Packit 9eaa09
			exp_digit = 0;
Packit 9eaa09
			totaldigits++;
Packit 9eaa09
		}
Packit 9eaa09
		if (!(a <= b))
Packit 9eaa09
			return -EINVAL;
Packit 9eaa09
		if (b >= nmaskbits)
Packit 9eaa09
			return -ERANGE;
Packit 9eaa09
		while (a <= b) {
Packit 9eaa09
			set_bit(a, maskp);
Packit 9eaa09
			a++;
Packit 9eaa09
		}
Packit 9eaa09
	} while (buflen && c == ',');
Packit 9eaa09
	return 0;
Packit 9eaa09
}