/*	set_range

Usage:

    #include	<qioret.h>	For error codes

    int
    set_range (values, range_map, limit)

    char	*values;	Values string
    int		*range_map;	Range map (bit) array
    int		limit;		Upper limit of values range (0-limit)


    rng_arg (arg_count, argument)

    int		arg_count;	Number of arguments in the argument list
    char	*argument[];	Argument list string pointers


Description:

set_range -

Dynamic memory is allocated to hold an argument list vector, which is created
from the parsed values string, which in turn is passed on to the local
range argument processing function (rng_arg).

The range_map is a bit array where a set bit indicates the corresponding
values have been selected as "in range".

The limit variable sets the maximum acceptable value for the range 0-limit.

The range_map pointer and the limit variable are stored in static memory for
use by the rng_arg function which may encounter indirect file references and
be called recursively.

The fucntion returns the status value set by the rng_arg function, or
IE_NBF if dynamic memory could not be allocated.


rng_arg -

The argument list vector is scanned for range information.  
The range information is used to set appropriate bits in the range map.
The argument strings can be of the form:

	value - the single type value is included.
	value0-value1 - the type values in the range value0 to value1
	    inclusive are included (value0 <= value1).
	filename - the contents of the indicated file contains a
	    types values list.  Multiple lines allowed; spaces ignored;
	    comments between '/''*' '*''/' pairs.
	combinations - any combination of the above comma separated.


The static status value is 0 on success, or an error code on failure.
The error code is IE_BAD (bad parameters) if values are out of range,
or an I/O error code if a problem occured with an indirect range file.

******************************************************************************/

#include	<std.h>
#include	<stdio.h>
#include	<qioret.h>
#include	<bit.h>

/* Delimiters for range arguments:
*/
static STRING	delimiters = " \t,";

/* Variables for use by the rng_arg function:
*/
static int	*range;		/* Bit map pointer */
static int	upper_limit;	/* Upper value limit */
static int	status = 0;	/* Function return status value */


int
set_range (values, range_map, limit)

STRING	values;
int	*range_map;
int	limit;
{
STRING	*argument;
STRING	old_delimiters;
extern STRING	white_space;

old_delimiters = white_space;
white_space = delimiters;

status = 0;
if (argument = malloc (80))
    {
    range = range_map;
    upper_limit = limit;
    rng_arg (arg_parse (values, argument), argument);
    mfree (argument);
    }
else
    status = IE_NBF;

white_space = old_delimiters;

return (status);
}


rng_arg (arg_count, argument)

int	arg_count;
STRING	argument[];
{
static int	value0, value1, offset;
static STRING	string;


while (arg_count--)
    {
    string = argument[arg_count];

    if (isdigit (*string))
	{
	/* Value argument */

	value0 = atoi (string);

	value1 = upper_limit;
	if (string = search (string, '-'))
	    {
	    if (isdigit (*(string = skip_white (++string))))
		value1 = atoi (string);
	    }
	else
	    value1 = value0;

	if (value0 > value1)
	    {
	    offset = value0;
	    value0 = value1;
	    value1 = value0;
	    }
	if (value0 < 0 || value1 > upper_limit)
	    status = IE_BAD;
	if (value1 >= 0)
	    {
	    value0 = (value0 >= 0) ? value0 : 0;
	    value1 = (value1 <= upper_limit) ? value1 : upper_limit;
	    for (; value0 <= value1; value0++)
		set_bit(range, value0);
	    }
	}

    else

	/* Filename argument */

	status = indirect (string, rng_arg);
    }
}
