1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
|
include <mach.h>
include <ctype.h>
define FIRST 1 # Default starting range
define LAST MAX_INT # Default ending range
define STEP 1 # Default step
define EOLIST 0 # End of list
# DECODE_RANGES -- Parse a string containing a list of integer numbers or
# ranges, delimited by either spaces or commas. Return as output a list
# of ranges defining a list of numbers, and the count of list numbers.
# Range limits must be positive nonnegative integers. ERR is returned as
# the function value if a conversion error occurs. The list of ranges is
# delimited by EOLIST.
int procedure decode_ranges (range_string, ranges, max_ranges, nvalues)
char range_string[ARB] # Range string to be decoded
int ranges[3, max_ranges] # Range array
int max_ranges # Maximum number of ranges
int nvalues # The number of values in the ranges
int ip, nrange, first, last, step, ctoi()
begin
ip = 1
nvalues = 0
do nrange = 1, max_ranges - 1 {
# Defaults to all nonnegative integers
first = FIRST
last = LAST
step = STEP
# Skip delimiters
while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
ip = ip + 1
# Get first limit.
# Must be a number, '-', 'x', or EOS. If not return ERR.
if (range_string[ip] == EOS) { # end of list
if (nrange == 1) {
# Null string defaults
ranges[1, 1] = first
ranges[2, 1] = last
ranges[3, 1] = step
ranges[1, 2] = EOLIST
nvalues = MAX_INT
return (OK)
} else {
ranges[1, nrange] = EOLIST
return (OK)
}
} else if (range_string[ip] == '-')
;
else if (range_string[ip] == 'x')
;
else if (IS_DIGIT(range_string[ip])) { # ,n..
if (ctoi (range_string, ip, first) == 0)
return (ERR)
} else
return (ERR)
# Skip delimiters
while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
ip = ip + 1
# Get last limit
# Must be '-', or 'x' otherwise last = first.
if (range_string[ip] == 'x')
;
else if (range_string[ip] == '-') {
ip = ip + 1
while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
ip = ip + 1
if (range_string[ip] == EOS)
;
else if (IS_DIGIT(range_string[ip])) {
if (ctoi (range_string, ip, last) == 0)
return (ERR)
} else if (range_string[ip] == 'x')
;
else
return (ERR)
} else
last = first
# Skip delimiters
while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
ip = ip + 1
# Get step.
# Must be 'x' or assume default step.
if (range_string[ip] == 'x') {
ip = ip + 1
while (IS_WHITE(range_string[ip]) || range_string[ip] == ',')
ip = ip + 1
if (range_string[ip] == EOS)
;
else if (IS_DIGIT(range_string[ip])) {
if (ctoi (range_string, ip, step) == 0)
;
if (step == 0)
return (ERR)
} else if (range_string[ip] == '-')
;
else
return (ERR)
}
# Output the range triple.
ranges[1, nrange] = first
ranges[2, nrange] = last
ranges[3, nrange] = step
nvalues = nvalues + abs (last-first) / step + 1
}
return (ERR) # ran out of space
end
# GET_NEXT_NUMBER -- Given a list of ranges and the current file number,
# find and return the next file number. Selection is done in such a way
# that list numbers are always returned in monotonically increasing order,
# regardless of the order in which the ranges are given. Duplicate entries
# are ignored. EOF is returned at the end of the list.
int procedure get_next_number (ranges, number)
int ranges[ARB] # Range array
int number # Both input and output parameter
int ip, first, last, step, next_number, remainder
begin
# If number+1 is anywhere in the list, that is the next number,
# otherwise the next number is the smallest number in the list which
# is greater than number+1.
number = number + 1
next_number = MAX_INT
for (ip=1; ranges[ip] != EOLIST; ip=ip+3) {
first = min (ranges[ip], ranges[ip+1])
last = max (ranges[ip], ranges[ip+1])
step = ranges[ip+2]
if (step == 0)
call error (1, "Step size of zero in range list")
if (number >= first && number <= last) {
remainder = mod (number - first, step)
if (remainder == 0)
return (number)
if (number - remainder + step <= last)
next_number = number - remainder + step
} else if (first > number)
next_number = min (next_number, first)
}
if (next_number == MAX_INT)
return (EOF)
else {
number = next_number
return (number)
}
end
# GET_PREVIOUS_NUMBER -- Given a list of ranges and the current file number,
# find and return the previous file number. Selection is done in such a way
# that list numbers are always returned in monotonically decreasing order,
# regardless of the order in which the ranges are given. Duplicate entries
# are ignored. EOF is returned at the end of the list.
int procedure get_previous_number (ranges, number)
int ranges[ARB] # Range array
int number # Both input and output parameter
int ip, first, last, step, next_number, remainder
begin
# If number-1 is anywhere in the list, that is the previous number,
# otherwise the previous number is the largest number in the list which
# is less than number-1.
number = number - 1
next_number = 0
for (ip=1; ranges[ip] != EOLIST; ip=ip+3) {
first = min (ranges[ip], ranges[ip+1])
last = max (ranges[ip], ranges[ip+1])
step = ranges[ip+2]
if (step == 0)
call error (1, "Step size of zero in range list")
if (number >= first && number <= last) {
remainder = mod (number - first, step)
if (remainder == 0)
return (number)
if (number - remainder >= first)
next_number = number - remainder
} else if (last < number) {
remainder = mod (last - first, step)
if (remainder == 0)
next_number = max (next_number, last)
else if (last - remainder >= first)
next_number = max (next_number, last - remainder)
}
}
if (next_number == 0)
return (EOF)
else {
number = next_number
return (number)
}
end
# IS_IN_RANGE -- Test number to see if it is in range.
# If the number is INDEFI then it is mapped to the maximum integer.
bool procedure is_in_range (ranges, number)
int ranges[ARB] # Range array
int number # Number to be tested against ranges
int ip, first, last, step, num
begin
if (IS_INDEFI (number))
num = MAX_INT
else
num = number
for (ip=1; ranges[ip] != EOLIST; ip=ip+3) {
first = min (ranges[ip], ranges[ip+1])
last = max (ranges[ip], ranges[ip+1])
step = ranges[ip+2]
if (num >= first && num <= last)
if (mod (num - first, step) == 0)
return (true)
}
return (false)
end
|