/* - exit - */ static int zexit(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref_stack_enum_t rsenum; uint scanned = 0; ref_stack_enum_begin(&rsenum, &e_stack); do { uint used = rsenum.size; es_ptr ep = rsenum.ptr + used - 1; uint count = used; for (; count; count--, ep--) if (r_is_estack_mark(ep)) switch (estack_mark_index(ep)) { case es_for: pop_estack(i_ctx_p, scanned + (used - count + 1)); return o_pop_estack; case es_stopped: return_error(e_invalidexit); /* not a loop */ } scanned += used; } while (ref_stack_enum_next(&rsenum)); /* No mark, quit. (per Adobe documentation) */ push(2); return unmatched_exit(op, zexit); }
/* Return 0 if we can't find the mark. */ static uint op_show_find_index(i_ctx_t *i_ctx_p) { ref_stack_enum_t rsenum; uint count = 0; ref_stack_enum_begin(&rsenum, &e_stack); do { es_ptr ep = rsenum.ptr; uint size = rsenum.size; for (ep += size - 1; size != 0; size--, ep--, count++) if (r_is_estack_mark(ep) && estack_mark_index(ep) == es_show) return count; } while (ref_stack_enum_next(&rsenum)); return 0; /* no mark */ }
/* * Pop the e-stack, executing cleanup procedures as needed. * We could make this more efficient using ref_stack_enum_*, * but it isn't used enough to make this worthwhile. */ void pop_estack(i_ctx_t *i_ctx_p, uint count) { uint idx = 0; uint popped = 0; esfile_clear_cache(); for (; idx < count; idx++) { ref *ep = ref_stack_index(&e_stack, idx - popped); if (r_is_estack_mark(ep)) { ref_stack_pop(&e_stack, idx + 1 - popped); popped = idx + 1; (*real_opproc(ep)) (i_ctx_p); } } ref_stack_pop(&e_stack, count - popped); }
/* * Count the number of elements down to and including the first 'stopped' * mark on the e-stack with a given mask. Return 0 if there is no 'stopped' * mark. */ static uint count_to_stopped(i_ctx_t *i_ctx_p, long mask) { ref_stack_enum_t rsenum; uint scanned = 0; ref_stack_enum_begin(&rsenum, &e_stack); do { uint used = rsenum.size; es_ptr ep = rsenum.ptr + used - 1; uint count = used; for (; count; count--, ep--) { if (r_is_estack_mark(ep)) { if (estack_mark_index(ep) == es_stopped && (ep[2].value.intval & mask) != 0) return scanned + (used - count + 1); } } scanned += used; } while (ref_stack_enum_next(&rsenum)); return 0; }