lists: fix various issues with the use of gnulib's list

First, we should avoid code such as

    gl_list_iterator_t it = gl_list_iterator (deriv->children);
    derivation *child = NULL;
    while (gl_list_iterator_next (&it, (const void **) &child, NULL))
      {
        derivation_print (child, f);

because of -Wstrict-aliasing (whose job is to catch type-punning
issues).  See https://lists.gnu.org/r/bug-bison/2020-05/msg00039.html.

Rather we need

    gl_list_iterator_t it = gl_list_iterator (deriv->children);
    const void **p = NULL;
    while (gl_list_iterator_next (&it, &p, NULL))
      {
        derivation *child = (derivation *) p;
        derivation_print (child, f);

Second, list iterators actually have destructors.  Even though they
are noop in the case of linked-lists, we should use them.

Let's address both issues with typed wrappers (such as
derivation_list_next) that take care of both issues, and besides allow
to scope the iterators within the loop:

    derivation *child;
    for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
         derivation_list_next (&it, &child);
         )
      {
        derivation_print (child, f);

* src/derivation.h, src/derivation.c (derivation_list_next): New.
Use it where appropriate.
* src/counterexample.c (search_state_list_next): New.
Use it where appropriate.
* src/parse-simulation.h, src/parse-simulation.c
* src/state-item.h (state_item_list_next): New.
Use it where appropriate.
This commit is contained in:
Akim Demaille
2020-05-31 09:22:39 +02:00
parent bb311cfbed
commit 742910838e
6 changed files with 170 additions and 96 deletions

View File

@@ -334,9 +334,9 @@ complete_diverging_example (symbol_number conflict_sym,
lookahead_required = false; lookahead_required = false;
derivation_list next_derivs = derivation_list next_derivs =
expand_to_conflict (nsi, conflict_sym); expand_to_conflict (nsi, conflict_sym);
gl_list_iterator_t it = gl_list_iterator (next_derivs);
derivation *d = NULL; derivation *d = NULL;
while (gl_list_iterator_next (&it, (const void **) &d, NULL)) for (gl_list_iterator_t it = gl_list_iterator (next_derivs);
derivation_list_next (&it, &d);)
derivation_list_append (result, d); derivation_list_append (result, d);
i += gl_list_size (next_derivs) - 1; i += gl_list_size (next_derivs) - 1;
derivation_list_free (next_derivs); derivation_list_free (next_derivs);
@@ -469,9 +469,10 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
if (trace_flag & trace_cex) if (trace_flag & trace_cex)
{ {
fputs ("SHIFT ITEM PATH:\n", stderr); fputs ("SHIFT ITEM PATH:\n", stderr);
gl_list_iterator_t it = gl_list_iterator (result);
state_item *sip = NULL; state_item *sip = NULL;
while (gl_list_iterator_next (&it, (const void **) &sip, NULL)) for (gl_list_iterator_t it = gl_list_iterator (result);
state_item_list_next (&it, &sip);
)
print_state_item (sip, stderr); print_state_item (sip, stderr);
} }
return result; return result;
@@ -574,6 +575,18 @@ search_state_print (search_state *ss)
putc ('\n', stderr); putc ('\n', stderr);
} }
static inline bool
search_state_list_next (gl_list_iterator_t *it, search_state **ss)
{
const void *p = NULL;
bool res = gl_list_iterator_next (it, &p, NULL);
if (res)
*ss = (search_state*) p;
else
gl_list_iterator_free (it);
return res;
}
/* /*
* When a search state is copied, this is used to * When a search state is copied, this is used to
* directly set one of the parse states * directly set one of the parse states
@@ -712,9 +725,10 @@ production_step (search_state *ss, int parser_state)
simulate_production (ss->states[parser_state], other_sym); simulate_production (ss->states[parser_state], other_sym);
int complexity = ss->complexity + PRODUCTION_COST; int complexity = ss->complexity + PRODUCTION_COST;
gl_list_iterator_t it = gl_list_iterator (prods);
parse_state *ps = NULL; parse_state *ps = NULL;
while (gl_list_iterator_next (&it, (const void **) &ps, NULL)) for (gl_list_iterator_t it = gl_list_iterator (prods);
parse_state_list_next (&it, &ps);
)
{ {
search_state *copy = copy_search_state (ss); search_state *copy = copy_search_state (ss);
ss_set_parse_state (copy, parser_state, ps); ss_set_parse_state (copy, parser_state, ps);
@@ -761,9 +775,10 @@ reduction_step (search_state *ss, const item_number *conflict_item,
// FIXME: search_state *new_root = copy_search_state (ss); // FIXME: search_state *new_root = copy_search_state (ss);
parse_state_list reduced = parse_state_list reduced =
simulate_reduction (ps, rule_len, symbol_set); simulate_reduction (ps, rule_len, symbol_set);
gl_list_iterator_t it = gl_list_iterator (reduced); parse_state *reduced_ps = NULL;
parse_state *reduced_ps; for (gl_list_iterator_t it = gl_list_iterator (reduced);
while (gl_list_iterator_next (&it, (const void **) &reduced_ps, NULL)) parse_state_list_next (&it, &reduced_ps);
)
{ {
search_state *copy = copy_search_state (ss); search_state *copy = copy_search_state (ss);
ss_set_parse_state (copy, parser_state, reduced_ps); ss_set_parse_state (copy, parser_state, reduced_ps);
@@ -797,9 +812,10 @@ search_state_prepend (search_state *ss, symbol_number sym, bitset guide)
{ {
int prod_state = prod1 ? 0 : 1; int prod_state = prod1 ? 0 : 1;
parse_state_list prev = parser_prepend (ss->states[prod_state]); parse_state_list prev = parser_prepend (ss->states[prod_state]);
gl_list_iterator_t iter = gl_list_iterator (prev);
parse_state *ps = NULL; parse_state *ps = NULL;
while (gl_list_iterator_next (&iter, (const void **)&ps, NULL)) for (gl_list_iterator_t iter = gl_list_iterator (prev);
parse_state_list_next (&iter, &ps);
)
{ {
const state_item *psi = parse_state_head (ps); const state_item *psi = parse_state_head (ps);
bool guided = bitset_test (guide, psi->state->number); bool guided = bitset_test (guide, psi->state->number);
@@ -828,18 +844,20 @@ search_state_prepend (search_state *ss, symbol_number sym, bitset guide)
// loop through each pair of possible prepend states and append search // loop through each pair of possible prepend states and append search
// states for each pair where the parser states correspond to the same // states for each pair where the parser states correspond to the same
// parsed input. // parsed input.
gl_list_iterator_t iter1 = gl_list_iterator (prev1); parse_state *ps1 = NULL;
parse_state *ps1; for (gl_list_iterator_t iter1 = gl_list_iterator (prev1);
while (gl_list_iterator_next (&iter1, (const void **)&ps1, NULL)) parse_state_list_next (&iter1, &ps1);
)
{ {
const state_item *psi1 = parse_state_head (ps1); const state_item *psi1 = parse_state_head (ps1);
bool guided1 = bitset_test (guide, psi1->state->number); bool guided1 = bitset_test (guide, psi1->state->number);
if (!guided1 && !EXTENDED_SEARCH) if (!guided1 && !EXTENDED_SEARCH)
continue; continue;
gl_list_iterator_t iter2 = gl_list_iterator (prev2); parse_state *ps2 = NULL;
parse_state *ps2; for (gl_list_iterator_t iter2 = gl_list_iterator (prev2);
while (gl_list_iterator_next (&iter2, (const void **)&ps2, NULL)) parse_state_list_next (&iter2, &ps2);
)
{ {
const state_item *psi2 = parse_state_head (ps2); const state_item *psi2 = parse_state_head (ps2);
@@ -926,16 +944,15 @@ generate_next_states (search_state *ss, state_item *conflict1,
int complexity = ss->complexity + 2 * SHIFT_COST; int complexity = ss->complexity + 2 * SHIFT_COST;
parse_state_list trans1 = simulate_transition (ps1); parse_state_list trans1 = simulate_transition (ps1);
parse_state_list trans2 = simulate_transition (ps2); parse_state_list trans2 = simulate_transition (ps2);
gl_list_iterator_t it1 = gl_list_iterator (trans1); parse_state *tps1 = NULL;
parse_state *tps1; parse_state *tps2 = NULL;
while (gl_list_iterator_next (&it1, (const void **) &tps1, NULL)) for (gl_list_iterator_t it1 = gl_list_iterator (trans1);
{ parse_state_list_next (&it1, &tps1);
gl_list_iterator_t it2 = gl_list_iterator (trans2); )
parse_state *tps2; for (gl_list_iterator_t it2 = gl_list_iterator (trans2);
while (gl_list_iterator_next parse_state_list_next (&it2, &tps2);
(&it2, (const void **) &tps2, NULL)) )
ssb_append (new_search_state (tps1, tps2, complexity)); ssb_append (new_search_state (tps1, tps2, complexity));
}
gl_list_free (trans1); gl_list_free (trans1);
gl_list_free (trans2); gl_list_free (trans2);
} }
@@ -958,43 +975,48 @@ generate_next_states (search_state *ss, state_item *conflict1,
int len2 = rhe2 - rhs2; int len2 = rhe2 - rhs2;
int size2 = parse_state_length (ps2); int size2 = parse_state_length (ps2);
bool ready2 = si2reduce && len2 < size2; bool ready2 = si2reduce && len2 < size2;
// If there is a path ready for reduction // If there is a path ready for reduction without being
// without being prepended further, reduce. // prepended further, reduce.
if (ready1) if (ready1 && ready2)
{ {
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1); gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1);
gl_list_iterator_t iter = gl_list_iterator (reduced1); gl_list_add_last (reduced1, ss);
search_state *red1 = NULL; search_state *red1 = NULL;
if (ready2) for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1);
)
{ {
gl_list_add_last (reduced1, ss); gl_list_t reduced2 =
while (gl_list_iterator_next reduction_step (red1, conflict2->item, 1, len2);
(&iter, (const void **) &red1, NULL)) search_state *red2 = NULL;
{ for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
gl_list_t reduced2 = search_state_list_next (&iter2, &red2);
reduction_step (red1, conflict2->item, 1, len2); )
gl_list_iterator_t iter2 = gl_list_iterator (reduced2); ssb_append (red2);
search_state *red2; // Avoid duplicates.
while (gl_list_iterator_next if (red1 != ss)
(&iter2, (const void **) &red2, NULL)) ssb_append (red1);
ssb_append (red2); gl_list_free (reduced2);
// avoid duplicates
if (red1 != ss)
ssb_append (red1);
gl_list_free (reduced2);
}
} }
else gl_list_free (reduced1);
while (gl_list_iterator_next (&iter, (const void **) &red1, NULL)) }
ssb_append (red1); else if (ready1)
{
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1);
search_state *red1 = NULL;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1);
)
ssb_append (red1);
gl_list_free (reduced1); gl_list_free (reduced1);
} }
else if (ready2) else if (ready2)
{ {
gl_list_t reduced2 = reduction_step (ss, conflict2->item, 1, len2); gl_list_t reduced2 = reduction_step (ss, conflict2->item, 1, len2);
gl_list_iterator_t iter2 = gl_list_iterator (reduced2); search_state *red2 = NULL;
search_state *red2; for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
while (gl_list_iterator_next (&iter2, (const void **) &red2, NULL)) search_state_list_next (&iter2, &red2);
)
ssb_append (red2); ssb_append (red2);
gl_list_free (reduced2); gl_list_free (reduced2);
} }
@@ -1046,9 +1068,11 @@ unifying_example (state_item_number itm1,
while (gl_list_size (ssb_queue) > 0) while (gl_list_size (ssb_queue) > 0)
{ {
const search_state_bundle *ssb = gl_list_get_at (ssb_queue, 0); const search_state_bundle *ssb = gl_list_get_at (ssb_queue, 0);
gl_list_iterator_t it = gl_list_iterator (ssb->states);
search_state *ss = NULL; search_state *ss = NULL;
while (gl_list_iterator_next (&it, (const void **) &ss, NULL)) for (gl_list_iterator_t it = gl_list_iterator (ssb->states);
search_state_list_next (&it, &ss);
)
{ {
if (trace_flag & trace_cex) if (trace_flag & trace_cex)
search_state_print (ss); search_state_print (ss);
@@ -1157,19 +1181,21 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
// Compute the shortest lookahead-sensitive path and associated sets of // Compute the shortest lookahead-sensitive path and associated sets of
// parser states. // parser states.
gl_list_t shortest_path = shortest_path_from_start (itm1, next_sym); gl_list_t shortest_path = shortest_path_from_start (itm1, next_sym);
bool reduceProdReached = false; bool reduce_prod_reached = false;
const rule *reduce_rule = item_rule (state_items[itm1].item); const rule *reduce_rule = item_rule (state_items[itm1].item);
bitset_zero (scp_set); bitset_zero (scp_set);
bitset_zero (rpp_set); bitset_zero (rpp_set);
gl_list_iterator_t it = gl_list_iterator (shortest_path);
state_item *si = NULL; state_item *si = NULL;
while (gl_list_iterator_next (&it, (const void **) &si, NULL)) for (gl_list_iterator_t it = gl_list_iterator (shortest_path);
state_item_list_next (&it, &si);
)
{ {
bitset_set (scp_set, si->state->number); bitset_set (scp_set, si->state->number);
reduceProdReached = reduceProdReached reduce_prod_reached = reduce_prod_reached
|| item_rule (si->item) == reduce_rule; || item_rule (si->item) == reduce_rule;
if (reduceProdReached) if (reduce_prod_reached)
bitset_set (rpp_set, si->state->number); bitset_set (rpp_set, si->state->number);
} }
time_t t = time (NULL); time_t t = time (NULL);

View File

@@ -55,9 +55,10 @@ derivation_list_prepend (derivation_list dl, derivation *d)
void derivation_list_free (derivation_list dl) void derivation_list_free (derivation_list dl)
{ {
gl_list_iterator_t it = gl_list_iterator (dl); derivation *d = NULL;
derivation *d; for (gl_list_iterator_t it = gl_list_iterator (dl);
while (gl_list_iterator_next (&it, (const void **) &d, NULL)) derivation_list_next (&it, &d);
)
if (d != &d_dot) if (d != &d_dot)
derivation_free (d); derivation_free (d);
gl_list_free (dl); gl_list_free (dl);
@@ -94,9 +95,10 @@ derivation_free (derivation *d)
{ {
if (deriv->children) if (deriv->children)
{ {
gl_list_iterator_t it = gl_list_iterator (deriv->children); derivation *child = NULL;
derivation *child; for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
while (gl_list_iterator_next (&it, (const void **) &child, NULL)) derivation_list_next (&it, &child);
)
if (child != &d_dot) if (child != &d_dot)
gl_list_add_last (free_queue, child); gl_list_add_last (free_queue, child);
gl_list_free (deriv->children); gl_list_free (deriv->children);
@@ -114,9 +116,10 @@ derivation_size (const derivation *deriv)
if (!deriv->children) if (!deriv->children)
return 1; return 1;
int size = 1; int size = 1;
gl_list_iterator_t it = gl_list_iterator (deriv->children); derivation *child = NULL;
derivation *child; for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
while (gl_list_iterator_next (&it, (const void **) &child, NULL)) derivation_list_next (&it, &child);
)
size += derivation_size (child); size += derivation_size (child);
return size; return size;
} }
@@ -136,10 +139,12 @@ derivation_print (const derivation *deriv, FILE *f)
fprintf (f, " %s", sym->tag); fprintf (f, " %s", sym->tag);
return; return;
} }
gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation *child;
fprintf (f, " %s ::=[", sym->tag); fprintf (f, " %s ::=[", sym->tag);
while (gl_list_iterator_next (&it, (const void **) &child, NULL)) derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
{ {
derivation_print (child, f); derivation_print (child, f);
fputs (" ", f); fputs (" ", f);
@@ -162,10 +167,11 @@ derivation_print_leaves (const derivation *deriv, FILE *f)
return; return;
} }
gl_list_iterator_t it = gl_list_iterator (deriv->children);
const char *sep = ""; const char *sep = "";
derivation *child; derivation *child;
while (gl_list_iterator_next (&it, (const void **) &child, NULL)) for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
{ {
fputs (sep, f); fputs (sep, f);
sep = " "; sep = " ";

View File

@@ -37,6 +37,18 @@ static inline derivation_list derivation_list_new (void)
return gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); return gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
} }
static inline bool
derivation_list_next (gl_list_iterator_t *it, derivation **d)
{
const void *p = NULL;
bool res = gl_list_iterator_next (it, &p, NULL);
if (res)
*d = (derivation *) p;
else
gl_list_iterator_free (it);
return res;
}
void derivation_list_append (derivation_list dl, derivation *d); void derivation_list_append (derivation_list dl, derivation *d);
void derivation_list_prepend (derivation_list dl, derivation *d); void derivation_list_prepend (derivation_list dl, derivation *d);
void derivation_list_free (derivation_list dl); void derivation_list_free (derivation_list dl);

View File

@@ -253,10 +253,12 @@ parse_state_completed_steps (const parse_state *ps, int *shifts, int *production
gl_list_t sis = root_ps->state_items.contents; gl_list_t sis = root_ps->state_items.contents;
int count = 0; int count = 0;
gl_list_iterator_t it = gl_list_iterator (sis);
state_item *last = NULL; state_item *last = NULL;
state_item *next = NULL; state_item *next = NULL;
while (gl_list_iterator_next (&it, (const void **) &next, NULL)) for (gl_list_iterator_t it = gl_list_iterator (sis);
state_item_list_next (&it, &next);
)
{ {
if (last && last->state == next->state) if (last && last->state == next->state)
++count; ++count;
@@ -285,22 +287,24 @@ list_flatten_and_split (gl_list_t *list, gl_list_t *rets, int split, int n,
int ret_array = 0; int ret_array = 0;
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
{ {
const void *p = NULL;
gl_list_iterator_t it = gl_list_iterator (list[i]); gl_list_iterator_t it = gl_list_iterator (list[i]);
gl_list_t l; while (gl_list_iterator_next (&it, &p, NULL))
while (gl_list_iterator_next (&it, (const void **) &l, NULL)) if (p)
{ {
if (!l) gl_list_t l = (gl_list_t) p;
continue; const void *si = NULL;
gl_list_iterator_t it2 = gl_list_iterator (l); gl_list_iterator_t it2 = gl_list_iterator (l);
void *si; while (gl_list_iterator_next (&it2, &si, NULL))
while (gl_list_iterator_next (&it2, (const void **) &si, NULL)) {
{ if (ret_index++ == split)
if (ret_index++ == split) ++ret_array;
++ret_array; if (rets[ret_array])
if (rets[ret_array]) append_fn (rets[ret_array], si);
append_fn (rets[ret_array], si); }
} gl_list_iterator_free (&it2);
} }
gl_list_iterator_free (&it);
} }
} }
@@ -540,11 +544,12 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
} }
else else
{ {
gl_list_iterator_t it = gl_list_iterator (prev); state_item *psis = NULL;
state_item *psis; for (gl_list_iterator_t it = gl_list_iterator (prev);
while (gl_list_iterator_next (&it, (const void **) &psis, NULL)) state_item_list_next (&it, &psis);
)
{ {
//Prepend the result from the reverse production // Prepend the result from the reverse production.
parse_state *copy = copy_parse_state (true, new_root); parse_state *copy = copy_parse_state (true, new_root);
ps_si_prepend (copy, psis); ps_si_prepend (copy, psis);

View File

@@ -74,6 +74,18 @@
typedef struct parse_state parse_state; typedef struct parse_state parse_state;
typedef gl_list_t parse_state_list; typedef gl_list_t parse_state_list;
static inline bool
parse_state_list_next (gl_list_iterator_t *it, parse_state **ps)
{
const void *p = NULL;
bool res = gl_list_iterator_next (it, &p, NULL);
if (res)
*ps = (parse_state *) p;
else
gl_list_iterator_free (it);
return res;
}
parse_state *new_parse_state (const state_item *conflict); parse_state *new_parse_state (const state_item *conflict);
size_t parse_state_hasher (const parse_state *ps, size_t max); size_t parse_state_hasher (const parse_state *ps, size_t max);

View File

@@ -92,4 +92,17 @@ void state_items_free (void);
bool production_allowed (const state_item *si, const state_item *next); bool production_allowed (const state_item *si, const state_item *next);
static inline bool
state_item_list_next (gl_list_iterator_t *it, state_item **si)
{
const void *p = NULL;
bool res = gl_list_iterator_next (it, &p, NULL);
if (res)
*si = (state_item *) p;
else
gl_list_iterator_free (it);
return res;
}
#endif /* STATE_ITEM_H */ #endif /* STATE_ITEM_H */