I’m looking at routine WriteListR()
from ListWriter.i6t
. The routine makes use of a @push instruction to temporarily store the value of global variable listing_size
as part of a else
clause taking place within a larger for
loop. Within the same else
clause, there is an opportunity to jump
out of the past the code that includes the @pull. It looks like when this happens, the matching @pull instruction will never occur.for
loop entirely
[ WriteListR o depth from_start
partition_classes partition_class_sizes
...
for (cl=1, memb=o, index=0, current_lt=EMPTY_TEXT_VALUE: groups_to_do>0: cl++) {
...
if ((LT_Compare(memb.list_together, lt_value) == 0) ||
(LT_Compare(memb.list_together, EMPTY_TEXT_VALUE) == 0))
current_lt = EMPTY_TEXT_VALUE;
else { ! current member LT meaningful and different from global LT
if (LT_Compare(memb.list_together, current_lt) == 0) continue;
! Otherwise this class begins a new group
@push listing_size; ! <-- @push always happens if else clause entered
q = memb; listing_size = 1; l = index; m = cl;
while (m < no_classes && (LT_Compare(q.list_together, memb.list_together) == 0)) {
m++; ! next class
while (partition_classes->l ~= m) { ! find first member of next class
l++; q = c_iterator(q, depth, lt_value, ADVANCE_ITF);
}
if (LT_Compare(q.list_together, memb.list_together) == 0)
listing_size++;
}
if (listing_size > 1) {
! The new group contains more than one partition class
WriteMultiClassGroup(cl, memb, depth, partition_class_sizes);
current_lt = memb.list_together;
jump GroupComplete; ! <-- if branching here, creates unbalanced @push/@pull?
}
current_lt = EMPTY_TEXT_VALUE;
@pull listing_size; ! <-- corresponding @pull happens here
}
WriteSingleClassGroup(cl, memb, depth, partition_class_sizes->cl);
.GroupComplete; ! <-- jump target past block including @pull
...
}
FreeStack(partition_class_sizes);
FreeStack(partition_classes);
]; ! end of WriteListR