/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#include "mrilib.h"
extern int *z_rand_order(int bot, int top, long int seed);
static int allow_negative = 0 ;
/*! Allow negative indexes in MCW_get_intlist() */
void MCW_intlist_allow_negative( int iii ) /* 22 Nov 1999 */
{
allow_negative = iii ; return ;
}
/*! Stopping criterion for MCW_get_intlist() ZSS, Aug 06: Added '#' to ISEND */
#define ISEND(c) ( (c)==']' || (c)=='}' || (c)=='#' || (c)=='\0' )
int * get_count_intlist ( char *str , int *nret)
{
int *subv = NULL, *ret = NULL ;
int ii , ipos , nout , slen, shuffle, step, itmp;
int ibot,itop,istep , nused , nuni;
long int seed=0;
char *cpt ;
*nret = -1;
if (!str || !strstr(str,"count ") || strlen (str) < 8) {
fprintf(stderr, "NULL input or string does not have 'count ' or at least 2 values are not present after 'count '\n");
return (NULL);
}
/* move past count */
slen = strlen(str) ;
ipos = strlen("count ");
/* see if you have seed */
if (strstr(str, "-seed ")) {
ipos = (strstr(str, "-seed ")-str)+strlen("-seed ");
seed = strtol( str+ipos , &cpt , 10 ) ;
nused = (cpt-(str+ipos)) ;
ipos += nused ;
}
/* get first value */
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
if( ISEND(str[ipos]) ) return NULL ; /* bad */
ibot = strtol( str+ipos , &cpt , 10 ) ;
if( ibot < 0 && !allow_negative ){
fprintf(stderr,"** ERROR: sub-brick index %d cannot be < 0\n",
ibot) ;
}
nused = (cpt-(str+ipos)) ;
if( ibot == 0 && nused == 0 ){
fprintf(stderr,"** ERROR: sub-brick syntax error '%s'\n",str+ipos) ;
return NULL ;
}
ipos += nused ;
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
if( ISEND(str[ipos]) ) return NULL ; /* Bad */
itop = strtol( str+ipos , &cpt , 10 ) ;
if( itop < 0 && !allow_negative ){
fprintf(stderr,"** ERROR: sub-brick index %d cannot be < 0\n",
itop) ;
return NULL ;
}
if( itop == 0 && nused == 0 ){
fprintf(stderr,"** ERROR: sub-brick syntax error '%s'\n",str+ipos) ;
return NULL ;
}
nused = (cpt-(str+ipos)) ;
ipos += nused ;
shuffle = 0;
step = 0;
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
if( !ISEND(str[ipos]) ) { /* have step */
if ( (str[ipos] >= 'A' && str[ipos]<='Z') ||
(str[ipos] >= 'a' && str[ipos]<='z') ) {
/* only S is acceptable here */
if (str[ipos] == 'S' || str[ipos] == 's') {
shuffle = 1;
++ipos;
}else {
fprintf(stderr,"** No qualifiers allowed for step, other than 'S'. Have %c.\n", str[ipos]);
return NULL ;
}
}
if( !ISEND(str[ipos]) ) {
step = strtol( str+ipos , &cpt , 10 ) ;
}
}
nused = (cpt-(str+ipos)) ;
ipos += nused ;
if (step < 0) {
fprintf(stderr,"** step must be > 0. Have %d.\n", step);
return NULL ;
}
/* fprintf(stderr,"Have count parameters: %d to %d with step %d and shuffle = %d; seed = %ld\n", ibot, itop, step, shuffle, seed); */
if (itop < ibot) {nuni = ibot - itop + 1;}
else { nuni = itop - ibot + 1; }
if (shuffle) {
subv = z_rand_order(ibot, itop, seed);
if (step > 0) {
*nret = step;
} else {
*nret = nuni;
}
} else {
*nret = nuni;
subv = (int *)malloc(sizeof(int)*(*nret));
if (!step) {
if (itop < ibot) step = -1;
else step = 1;
} else {
if (itop < ibot) step *= -1;
else step *= 1;
}
itmp = 0;
if (itop < ibot) for (ii=ibot; ii>=itop;ii=ii+step) { subv[itmp] = ii; ++itmp; }
else for (ii=ibot; ii<=itop;ii=ii+step) { subv[itmp] = ii; ++itmp; }
*nret = itmp;
}
/* fprintf(stderr,"Have %d ints: %d to %d with step %d and shuffle = %d\n", *nret, ibot, itop, step, shuffle); */
ret = (int *)malloc(sizeof(int)*(*nret+1));
ret[0] = *nret;
for (ii=1; ii<=ret[0]; ++ii) ret[ii] = subv[(ii-1)%(nuni)];
free(subv); subv = ret;
/* for (ii=0; ii<=ret[0]; ++ii) fprintf(stderr,"%d: %d\n", ii, subv[ii]); */
return(subv);
}
/*-----------------------------------------------------------------*/
/*! Get an integer list in the range 0..(nvals-1), from the
character string str. If we call the output pointer fred,
then fred[0] = number of integers in the list (> 0), and
fred[i] = i-th integer in the list for i=1..fred[0].
If on return, fred == NULL or fred[0] == 0, then something is
wrong, and the caller must deal with that.
Syntax of input string:
- initial '{' or '[' or '#' is skipped, if present
- ends when '}' or ']' or '#' or end of string is found
- contains entries separated by commas
- entries have one of these forms:
- a single number
- a dollar sign '$', which means nvals-1
- a sequence of consecutive numbers in the form "a..b" or
"a-b", where "a" and "b" are single numbers (or '$')
- a sequence of evenly spaced numbers in the form
"a..b(c)" or "a-b(c)", where "c" encodes the step
- Example: "[2,7..4,3..9(2)]" decodes to the list
2 7 6 5 4 3 5 7 9
- entries should be in the range 0..nvals-1
-------------------------------------------------------------------*/
int * MCW_get_intlist( int nvals , char *str )
{
int *subv = NULL ;
int ii , ipos , nout , slen ;
int ibot,itop,istep , nused ;
char *cpt ;
/* Meaningless input? */
if( nvals < 1 ) return NULL ;
/* No selection list? */
if( str == NULL || str[0] == '\0' ) return NULL ;
/* skip initial '[' or '{' or '#'*/
subv = (int *) malloc( sizeof(int) * 2 ) ;
subv[0] = nout = 0 ;
ipos = 0 ;
if( str[ipos] == '[' || str[ipos] == '{' || str[ipos] == '#') ipos++ ;
/* do we have a count string in there ZSS ? */
if (strstr(str,"count ")) {
return(get_count_intlist ( str, &ii));
}
/*** loop through each sub-selector until end of input ***/
slen = strlen(str) ;
while( ipos < slen && !ISEND(str[ipos]) ){
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
if( ISEND(str[ipos]) ) break ; /* done */
/** get starting value **/
if( str[ipos] == '$' ){ /* special case */
ibot = nvals-1 ; ipos++ ;
} else { /* decode an integer */
ibot = strtol( str+ipos , &cpt , 10 ) ;
if( ibot < 0 && !allow_negative ){
fprintf(stderr,"** ERROR: sub-brick index %d is out of range 0..%d\n",
ibot,nvals-1) ;
free(subv) ; return NULL ;
}
if( ibot >= nvals ){
fprintf(stderr,"** ERROR: sub-brick index %d is out of range 0..%d\n",
ibot,nvals-1) ;
free(subv) ; return NULL ;
}
nused = (cpt-(str+ipos)) ;
if( ibot == 0 && nused == 0 ){
fprintf(stderr,"** ERROR: sub-brick syntax error '%s'\n",str+ipos) ;
free(subv) ; return NULL ;
}
ipos += nused ;
}
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
/** if that's it for this sub-selector, add one value to list **/
if( str[ipos] == ',' || ISEND(str[ipos]) ){
nout++ ;
subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
subv[0] = nout ;
subv[nout] = ibot ;
if( ISEND(str[ipos]) ) break ; /* done */
ipos++ ; continue ; /* re-start loop at next sub-selector */
}
/** otherwise, must have '..' or '-' as next inputs **/
if( str[ipos] == '-' ){
ipos++ ;
} else if( str[ipos] == '.' && str[ipos+1] == '.' ){
ipos++ ; ipos++ ;
} else {
fprintf(stderr,"** ERROR: sub-brick selector syntax is bad: '%s'\n",
str+ipos) ;
free(subv) ; return NULL ;
}
/** get ending value for loop now **/
if( str[ipos] == '$' ){ /* special case */
itop = nvals-1 ; ipos++ ;
} else { /* decode an integer */
itop = strtol( str+ipos , &cpt , 10 ) ;
if( itop < 0 && !allow_negative ){
fprintf(stderr,"** ERROR: sub-brick index %d is out of range 0..%d\n",
itop,nvals-1) ;
free(subv) ; return NULL ;
}
if( itop >= nvals ){
fprintf(stderr,"** ERROR: sub-brick index %d is out of range 0..%d\n",
itop,nvals-1) ;
free(subv) ; return NULL ;
}
nused = (cpt-(str+ipos)) ;
if( itop == 0 && nused == 0 ){
fprintf(stderr,"** ERROR: sub-brick syntax error '%s'\n",str+ipos) ;
free(subv) ; return NULL ;
}
ipos += nused ;
}
/** set default loop step **/
istep = (ibot <= itop) ? 1 : -1 ;
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
/** check if we have a non-default loop step **/
if( str[ipos] == '(' ){ /* decode an integer */
ipos++ ;
istep = strtol( str+ipos , &cpt , 10 ) ;
if( istep == 0 ){
fprintf(stderr,"** ERROR: sub-brick loop step is 0!\n") ;
free(subv) ; return NULL ;
}
nused = (cpt-(str+ipos)) ;
ipos += nused ;
if( str[ipos] == ')' ) ipos++ ;
if( (ibot-itop)*istep > 0 ){
fprintf(stderr,"** WARNING: sub-brick count '%d..%d(%d)' means nothing!\n",
ibot,itop,istep ) ;
}
}
/** add values to output **/
for( ii=ibot ; (ii-itop)*istep <= 0 ; ii += istep ){
nout++ ;
subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
subv[0] = nout ;
subv[nout] = ii ;
}
/** check if we have a comma to skip over **/
while( isspace(str[ipos]) ) ipos++ ; /* skip blanks */
if( str[ipos] == ',' ) ipos++ ; /* skip commas */
} /* end of loop through selector string */
if( subv[0] == 0 ){ free(subv); subv = NULL; }
return subv ;
}
syntax highlighted by Code2HTML, v. 0.9.1