| File: | backend/dvi/mdvi-lib/pagesel.c |
| Warning: | line 59, column 2 Value stored to 'lower' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* pagesel.c -- Page selection mechanism */ |
| 2 | /* |
| 3 | * Copyright (C) 2000, Matias Atria |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation; either version 2 of the License, or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 18 | */ |
| 19 | |
| 20 | #include <config.h> |
| 21 | #include <stdlib.h> |
| 22 | #include <ctype.h> |
| 23 | #include <string.h> |
| 24 | #include <limits.h> |
| 25 | |
| 26 | #include "mdvi.h" |
| 27 | #include "private.h" |
| 28 | |
| 29 | char *program_name = "page"; |
| 30 | |
| 31 | struct _DviPageSpec { |
| 32 | DviRange *ranges; |
| 33 | int nranges; |
| 34 | }; |
| 35 | |
| 36 | DviRange *mdvi_parse_range(const char *format, DviRange *limit, int *nitems, char **endptr) |
| 37 | { |
| 38 | int quoted; |
| 39 | int size; |
| 40 | int curr; |
| 41 | int done; |
| 42 | int lower; |
| 43 | int upper; |
| 44 | int type; |
| 45 | char * cp; |
| 46 | char * copy; |
| 47 | char * text; |
| 48 | DviRange one; |
| 49 | DviRange *range; |
| 50 | |
| 51 | quoted = (*format == '{'); |
| 52 | if(quoted) format++; |
| 53 | |
| 54 | size = 0; |
| 55 | curr = 0; |
| 56 | range = NULL((void*)0); |
| 57 | copy = mdvi_strdup(format); |
| 58 | done = 0; |
| 59 | lower = 0; |
Value stored to 'lower' is never read | |
| 60 | upper = 0; |
| 61 | type = MDVI_RANGE_UNBOUNDED; |
| 62 | |
| 63 | if(limit) { |
| 64 | switch(limit->type) { |
| 65 | case MDVI_RANGE_BOUNDED: |
| 66 | lower = limit->from; |
| 67 | upper = limit->to; |
| 68 | break; |
| 69 | case MDVI_RANGE_UPPER: |
| 70 | lower = INT_MIN(-2147483647 -1); |
| 71 | upper = limit->to; |
| 72 | break; |
| 73 | case MDVI_RANGE_LOWER: |
| 74 | lower = limit->from; |
| 75 | upper = INT_MAX2147483647; |
| 76 | break; |
| 77 | case MDVI_RANGE_UNBOUNDED: |
| 78 | lower = INT_MIN(-2147483647 -1); |
| 79 | upper = INT_MAX2147483647; |
| 80 | break; |
| 81 | } |
| 82 | type = limit->type; |
| 83 | } else { |
| 84 | lower = INT_MIN(-2147483647 -1); |
| 85 | upper = INT_MAX2147483647; |
| 86 | type = MDVI_RANGE_UNBOUNDED; |
| 87 | } |
| 88 | one.type = type; |
| 89 | one.from = lower; |
| 90 | one.to = upper; |
| 91 | one.step = 1; |
| 92 | for(cp = text = copy; !done; cp++) { |
| 93 | char *p; |
| 94 | int f, t, s; |
| 95 | int ch; |
| 96 | int this_type; |
| 97 | int lower_given = 0; |
| 98 | int upper_given = 0; |
| 99 | |
| 100 | if(*cp == 0 || *cp == '.' || (*cp == '}' && quoted)) |
| 101 | done = 1; |
| 102 | else if(*cp != ',') |
| 103 | continue; |
| 104 | |
| 105 | if(text == cp) |
| 106 | continue; |
| 107 | ch = *cp; |
| 108 | *cp = 0; |
| 109 | f = lower; |
| 110 | t = upper; |
| 111 | s = 1; |
| 112 | |
| 113 | p = strchr(text, ':'); |
| 114 | if(p) *p++ = 0; |
| 115 | if(*text) { |
| 116 | lower_given = 1; |
| 117 | f = strtol(text, NULL((void*)0), 0); |
| 118 | } |
| 119 | if(p == NULL((void*)0)) { |
| 120 | if(lower_given) { |
| 121 | upper_given = 1; |
| 122 | t = f; s = 1; |
| 123 | } |
| 124 | goto finish; |
| 125 | } |
| 126 | text = p; |
| 127 | p = strchr(text, ':'); |
| 128 | if(p) *p++ = 0; |
| 129 | if(*text) { |
| 130 | upper_given = 1; |
| 131 | t = strtol(text, NULL((void*)0), 0); |
| 132 | } |
| 133 | if(p == NULL((void*)0)) |
| 134 | goto finish; |
| 135 | text = p; |
| 136 | if(*text) |
| 137 | s = strtol(text, NULL((void*)0), 0); |
| 138 | finish: |
| 139 | if(lower_given && upper_given) |
| 140 | this_type = MDVI_RANGE_BOUNDED; |
| 141 | else if(lower_given) { |
| 142 | if(!RANGE_HAS_UPPER(type)((type) == MDVI_RANGE_BOUNDED || (type) == MDVI_RANGE_UPPER)) |
| 143 | this_type = MDVI_RANGE_LOWER; |
| 144 | else |
| 145 | this_type = MDVI_RANGE_BOUNDED; |
| 146 | t = upper; |
| 147 | } else if(upper_given) { |
| 148 | if(RANGE_HAS_UPPER(one.type)((one.type) == MDVI_RANGE_BOUNDED || (one.type) == MDVI_RANGE_UPPER )) { |
| 149 | one.to++; |
| 150 | this_type = MDVI_RANGE_BOUNDED; |
| 151 | } else { |
| 152 | one.to = lower; |
| 153 | if(!RANGE_HAS_LOWER(type)((type) == MDVI_RANGE_BOUNDED || (type) == MDVI_RANGE_LOWER)) |
| 154 | this_type = MDVI_RANGE_UPPER; |
| 155 | else |
| 156 | this_type = MDVI_RANGE_BOUNDED; |
| 157 | } |
| 158 | f = one.to; |
| 159 | } else { |
| 160 | this_type = type; |
| 161 | f = lower; |
| 162 | t = upper; |
| 163 | } |
| 164 | one.type = this_type; |
| 165 | one.to = t; |
| 166 | one.from = f; |
| 167 | one.step = s; |
| 168 | |
| 169 | if(curr == size) { |
| 170 | size += 8; |
| 171 | range = mdvi_realloc(range, size * sizeof(DviRange)); |
| 172 | } |
| 173 | memcpy(&range[curr++], &one, sizeof(DviRange))bcopy ((&one), (&range[curr++]), (sizeof(DviRange))); |
| 174 | *cp = ch; |
| 175 | text = cp + 1; |
| 176 | } |
| 177 | if(done) |
| 178 | cp--; |
| 179 | if(quoted && *cp == '}') |
| 180 | cp++; |
| 181 | if(endptr) |
| 182 | *endptr = (char *)format + (cp - copy); |
| 183 | if(curr && curr < size) |
| 184 | range = mdvi_realloc(range, curr * sizeof(DviRange)); |
| 185 | *nitems = curr; |
| 186 | mdvi_free(copy); |
| 187 | return range; |
| 188 | } |
| 189 | |
| 190 | DviPageSpec *mdvi_parse_page_spec(const char *format) |
| 191 | { |
| 192 | /* |
| 193 | * a page specification looks like this: |
| 194 | * '{'RANGE_SPEC'}' for a DVI spec |
| 195 | * '{'RANGE_SPEC'}' '.' ... for a TeX spec |
| 196 | */ |
| 197 | DviPageSpec *spec; |
| 198 | DviRange *range; |
| 199 | int count; |
| 200 | int i; |
| 201 | char *ptr; |
| 202 | |
| 203 | spec = xnalloc(struct _DviPageSpec *, 11)(struct _DviPageSpec * *)mdvi_calloc((11), sizeof(struct _DviPageSpec *)); |
| 204 | for(i = 0; i < 11; i++) |
| 205 | spec[i] = NULL((void*)0); |
| 206 | |
| 207 | /* check what kind of spec we're parsing */ |
| 208 | if(*format != '*') { |
| 209 | range = mdvi_parse_range(format, NULL((void*)0), &count, &ptr); |
| 210 | if(ptr == format) { |
| 211 | if(range) mdvi_free(range); |
| 212 | mdvi_error(_("invalid page specification `%s'\n")gettext("invalid page specification `%s'\n"), format); |
| 213 | return NULL((void*)0); |
| 214 | } |
| 215 | } else |
| 216 | range = NULL((void*)0); |
| 217 | |
| 218 | if(*format == 'D' || *format == 'd' || *ptr != '.') |
| 219 | i = 0; |
| 220 | else |
| 221 | i = 1; |
| 222 | |
| 223 | if(range) { |
| 224 | spec[i] = xalloc(struct _DviPageSpec)(struct _DviPageSpec *)mdvi_malloc(sizeof(struct _DviPageSpec )); |
| 225 | spec[i]->ranges = range; |
| 226 | spec[i]->nranges = count; |
| 227 | } else |
| 228 | spec[i] = NULL((void*)0); |
| 229 | |
| 230 | if(*ptr != '.') { |
| 231 | if(*ptr) |
| 232 | mdvi_warning(_("garbage after DVI page specification ignored\n")gettext("garbage after DVI page specification ignored\n")); |
| 233 | return spec; |
| 234 | } |
| 235 | |
| 236 | for(i++; *ptr == '.' && i <= 10; i++) { |
| 237 | ptr++; |
| 238 | if(*ptr == '*') { |
| 239 | ptr++; |
| 240 | range = NULL((void*)0); |
| 241 | } else { |
| 242 | char *end; |
| 243 | |
| 244 | range = mdvi_parse_range(ptr, NULL((void*)0), &count, &end); |
| 245 | if(end == ptr) { |
| 246 | if(range) mdvi_free(range); |
| 247 | range = NULL((void*)0); |
| 248 | } else |
| 249 | ptr = end; |
| 250 | } |
| 251 | if(range != NULL((void*)0)) { |
| 252 | spec[i] = xalloc(struct _DviPageSpec)(struct _DviPageSpec *)mdvi_malloc(sizeof(struct _DviPageSpec )); |
| 253 | spec[i]->ranges = range; |
| 254 | spec[i]->nranges = count; |
| 255 | } else |
| 256 | spec[i] = NULL((void*)0); |
| 257 | } |
| 258 | |
| 259 | if(i > 10) |
| 260 | mdvi_warning(_("more than 10 counters in page specification\n")gettext("more than 10 counters in page specification\n")); |
| 261 | else if(*ptr) |
| 262 | mdvi_warning(_("garbage after TeX page specification ignored\n")gettext("garbage after TeX page specification ignored\n")); |
| 263 | |
| 264 | return spec; |
| 265 | } |
| 266 | |
| 267 | /* returns non-zero if the given page is included by `spec' */ |
| 268 | int mdvi_page_selected(DviPageSpec *spec, PageNum page, int dvipage) |
| 269 | { |
| 270 | int i; |
| 271 | int not_found; |
| 272 | |
| 273 | if(spec == NULL((void*)0)) |
| 274 | return 1; |
| 275 | if(spec[0]) { |
| 276 | not_found = mdvi_in_range(spec[0]->ranges, |
| 277 | spec[0]->nranges, dvipage); |
| 278 | if(not_found < 0) |
| 279 | return 0; |
| 280 | } |
| 281 | for(i = 1; i <= 10; i++) { |
| 282 | if(spec[i] == NULL((void*)0)) |
| 283 | continue; |
| 284 | not_found = mdvi_in_range(spec[i]->ranges, |
| 285 | spec[i]->nranges, (int)page[i]); |
| 286 | if(not_found < 0) |
| 287 | return 0; |
| 288 | } |
| 289 | return 1; |
| 290 | } |
| 291 | |
| 292 | void mdvi_free_page_spec(DviPageSpec *spec) |
| 293 | { |
| 294 | int i; |
| 295 | |
| 296 | for(i = 0; i < 11; i++) |
| 297 | if(spec[i]) { |
| 298 | mdvi_free(spec[i]->ranges); |
| 299 | mdvi_free(spec[i]); |
| 300 | } |
| 301 | mdvi_free(spec); |
| 302 | } |
| 303 | |
| 304 | int mdvi_in_range(DviRange *range, int nitems, int value) |
| 305 | { |
| 306 | DviRange *r; |
| 307 | |
| 308 | for(r = range; r < range + nitems; r++) { |
| 309 | int cond; |
| 310 | |
| 311 | switch(r->type) { |
| 312 | case MDVI_RANGE_BOUNDED: |
| 313 | if(value == r->from) |
| 314 | return (r - range); |
| 315 | if(r->step < 0) |
| 316 | cond = (value <= r->from) && (value >= r->to); |
| 317 | else |
| 318 | cond = (value <= r->to) && (value >= r->from); |
| 319 | if(cond && ((value - r->from) % r->step) == 0) |
| 320 | return (r - range); |
| 321 | break; |
| 322 | case MDVI_RANGE_LOWER: |
| 323 | if(value == r->from) |
| 324 | return (r - range); |
| 325 | if(r->step < 0) |
| 326 | cond = (value < r->from); |
| 327 | else |
| 328 | cond = (value > r->from); |
| 329 | if(cond && ((value - r->from) % r->step) == 0) |
| 330 | return (r - range); |
| 331 | break; |
| 332 | case MDVI_RANGE_UPPER: |
| 333 | if(value == r->to) |
| 334 | return (r - range); |
| 335 | if(r->step < 0) |
| 336 | cond = (value > r->to); |
| 337 | else |
| 338 | cond = (value < r->to); |
| 339 | if(cond && ((value - r->to) % r->step) == 0) |
| 340 | return (r - range); |
| 341 | break; |
| 342 | case MDVI_RANGE_UNBOUNDED: |
| 343 | if((value % r->step) == 0) |
| 344 | return (r - range); |
| 345 | break; |
| 346 | } |
| 347 | } |
| 348 | return -1; |
| 349 | } |
| 350 | |
| 351 | int mdvi_range_length(DviRange *range, int nitems) |
| 352 | { |
| 353 | int count = 0; |
| 354 | DviRange *r; |
| 355 | |
| 356 | for(r = range; r < range + nitems; r++) { |
| 357 | int n; |
| 358 | |
| 359 | if(r->type != MDVI_RANGE_BOUNDED) |
| 360 | return -2; |
| 361 | n = (r->to - r->from) / r->step; |
| 362 | if(n < 0) |
| 363 | n = 0; |
| 364 | count += n + 1; |
| 365 | } |
| 366 | return count; |
| 367 | } |
| 368 | |
| 369 | #ifdef TEST |
| 370 | |
| 371 | void print_range(DviRange *range) |
| 372 | { |
| 373 | switch(range->type) { |
| 374 | case MDVI_RANGE_BOUNDED: |
| 375 | printf("From %d to %d, step %d\n", |
| 376 | range->from, range->to, range->step); |
| 377 | break; |
| 378 | case MDVI_RANGE_LOWER: |
| 379 | printf("From %d, step %d\n", |
| 380 | range->from, range->step); |
| 381 | break; |
| 382 | case MDVI_RANGE_UPPER: |
| 383 | printf("From %d, step -%d\n", |
| 384 | range->to, range->step); |
| 385 | break; |
| 386 | case MDVI_RANGE_UNBOUNDED: |
| 387 | printf("From 0, step %d and %d\n", |
| 388 | range->step, -range->step); |
| 389 | break; |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | int main() |
| 394 | { |
| 395 | #if 0 |
| 396 | char buf[256]; |
| 397 | DviRange limit; |
| 398 | |
| 399 | limit.from = 0; |
| 400 | limit.to = 100; |
| 401 | limit.step = 2; |
| 402 | limit.type = MDVI_RANGE_UNBOUNDED; |
| 403 | while(1) { |
| 404 | DviRange *range; |
| 405 | char *end; |
| 406 | int count; |
| 407 | int i; |
| 408 | |
| 409 | printf("Range> "); fflush(stdoutstdout); |
| 410 | if(fgets(buf, 256, stdinstdin) == NULL((void*)0)) |
| 411 | break; |
| 412 | if(buf[strlen(buf)-1] == '\n') |
| 413 | buf[strlen(buf)-1] = 0; |
| 414 | if(buf[0] == 0) |
| 415 | continue; |
| 416 | end = NULL((void*)0); |
| 417 | range = mdvi_parse_range(buf, &limit, &count, &end); |
| 418 | if(range == NULL((void*)0)) { |
| 419 | printf("range is empty\n"); |
| 420 | continue; |
| 421 | } |
| 422 | |
| 423 | for(i = 0; i < count; i++) { |
| 424 | printf("Range %d (%d elements):\n", |
| 425 | i, mdvi_range_length(&range[i], 1)); |
| 426 | print_range(&range[i]); |
| 427 | } |
| 428 | if(end && *end) |
| 429 | printf("Tail: [%s]\n", end); |
| 430 | printf("range has %d elements\n", |
| 431 | mdvi_range_length(range, count)); |
| 432 | #if 1 |
| 433 | while(1) { |
| 434 | int v; |
| 435 | |
| 436 | printf("Value: "); fflush(stdoutstdout); |
| 437 | if(fgets(buf, 256, stdinstdin) == NULL((void*)0)) |
| 438 | break; |
| 439 | if(buf[strlen(buf)-1] == '\n') |
| 440 | buf[strlen(buf)-1] = 0; |
| 441 | if(buf[0] == 0) |
| 442 | break; |
| 443 | v = atoi(buf); |
| 444 | i = mdvi_in_range(range, count, v); |
| 445 | if(i == -1) |
| 446 | printf("%d not in range\n", v); |
| 447 | else { |
| 448 | printf("%d in range: ", v); |
| 449 | print_range(&range[i]); |
| 450 | } |
| 451 | } |
| 452 | #endif |
| 453 | if(range) mdvi_free(range); |
| 454 | } |
| 455 | #else |
| 456 | DviPageSpec *spec; |
| 457 | char buf[256]; |
| 458 | |
| 459 | while(1) { |
| 460 | printf("Spec> "); fflush(stdoutstdout); |
| 461 | if(fgets(buf, 256, stdinstdin) == NULL((void*)0)) |
| 462 | break; |
| 463 | if(buf[strlen(buf)-1] == '\n') |
| 464 | buf[strlen(buf)-1] = 0; |
| 465 | if(buf[0] == 0) |
| 466 | continue; |
| 467 | spec = mdvi_parse_page_spec(buf); |
| 468 | if(spec == NULL((void*)0)) |
| 469 | printf("no spec parsed\n"); |
| 470 | else { |
| 471 | int i; |
| 472 | |
| 473 | printf("spec = "); |
| 474 | for(i = 0; i < 11; i++) { |
| 475 | printf("Counter %d:\n", i); |
| 476 | if(spec[i]) { |
| 477 | int k; |
| 478 | |
| 479 | for(k = 0; k < spec[i]->nranges; k++) |
| 480 | print_range(&spec[i]->ranges[k]); |
| 481 | } else |
| 482 | printf("\t*\n"); |
| 483 | } |
| 484 | mdvi_free_page_spec(spec); |
| 485 | } |
| 486 | } |
| 487 | #endif |
| 488 | exit(0); |
| 489 | |
| 490 | } |
| 491 | #endif /* TEST */ |