/***************************************************************************** * Push an expected state on the stack ****************************************************************************/ void dreme_push_es(PS_T *ps, PS_EN expected_state, ES_EN expected_occurances) { ES_T *es; if (expected_state < PS_ERROR || expected_state > PS_END) { die("Bad state code!\n"); } es = mm_malloc(sizeof(ES_T)); es->state = expected_state; es->expected = expected_occurances; es->found = 0; linklst_push(es, ps->expected_stack); }
/***************************************************************************** * At the start of a new element check that all previous expected elements * have been found and that the current element hasn't been repeated too * many times. ****************************************************************************/ int dreme_update_es(PS_T *ps, PS_EN next_state) { ES_T *es, old_es; if (next_state < PS_ERROR || next_state > PS_END) { die("Bad state code!\n"); } while ((es = (ES_T*)linklst_pop(ps->expected_stack)) != NULL && es->state != next_state) { old_es = *es; free(es); es = NULL; switch (old_es.expected) { case ES_ONCE: case ES_ONE_OR_MORE: if (old_es.found < 1){ error(ps, "Expected state %s not found!\n", state_names[old_es.state]); return FALSE; } default: break; } } if (es != NULL) { es->found += 1; linklst_push(es, ps->expected_stack); switch (es->expected) { case ES_ONCE: case ES_ZERO_OR_ONE: if (es->found > 1) { error(ps, "Expected state %s only once!\n", state_names[es->state]); return FALSE; } default: break; } } else { error(ps, "The state %s was not expected!\n", state_names[next_state]); return FALSE; } return TRUE; }
/* * pushes a new state onto the stack */ static void push_state(LINKLST_T* stack, JSON_EN state) { JSON_EN *allocated_state; allocated_state = mm_malloc(sizeof(JSON_EN)); *allocated_state = state; linklst_push(allocated_state, stack); }