/***************************************************************************** * Handle the document end ****************************************************************************/ void handle_dreme_end_doc(void *ctx) { PS_T *ps = (PS_T*)ctx; ES_T *es; if (ps->state != PS_ERROR) dreme_update_es(ps, PS_END); while ((es = (ES_T*)linklst_pop(ps->expected_stack)) != NULL) { free(es); } }
/* * pops the top state off the stack */ static JSON_EN pop_state(LINKLST_T* stack) { JSON_EN *allocated_state, state; if (!linklst_size(stack)) return JSON_ERROR; allocated_state = linklst_pop(stack); state = *allocated_state; free(allocated_state); return state; }
/***************************************************************************** * 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; }
MOTIF_T* dxml_next_motif(void *data) { DXML_T *parser; parser = (DXML_T*)data; return linklst_pop(parser->data->motif_queue); }
char* dxml_next_error(void *data) { DXML_T *parser; parser = (DXML_T*)data; return linklst_pop(parser->data->errors); }
/***************************************************************************** * Get the next motif. The caller is responsible for freeing the memory. ****************************************************************************/ MOTIF_T* mxml_next_motif(void *data) { MXML_T *parser; parser = (MXML_T*)data; return (MOTIF_T*)linklst_pop(parser->data->motif_queue); }
/***************************************************************************** * Get the next human readable error message detailing the * problem with the file. The caller is responsible for freeing the memory. ****************************************************************************/ char* mxml_next_error(void *data) { MXML_T *parser; parser = (MXML_T*)data; return (char*)linklst_pop(parser->data->errors); }
/***************************************************************************** * Get the next human readable warning message detailing the * problem with the file. The caller is responsible for freeing the memory. ****************************************************************************/ char* mxml_next_warning(void *data) { MXML_T *parser; parser = (MXML_T*)data; return (char*)linklst_pop(parser->data->warnings); }