/* Copyright (c) 2002-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file readau.c The readau module of the genau program. This module contains functions to read the state machine description from a file. */ #ifndef DEBUG /** No debugging at this time. */ #define DEBUG 0 #endif #include #include #include #include #include #include #include #include #include #include #include /** Inside the readau module. */ #define READAU_C 1 #include #include #if DK_HAVE_STDLIB_H #include #endif #if DK_HAVE_UNISTD_H #include #endif #if DK_HAVE_STRIN_H #include #endif #if DK_HAVE_STRINGS_H #include #endif $(trace-include) /** String: Opening bracket. */ static char str_bropen[] = { "(" }; /** String: Closing bracket. */ static char str_brclose[] = { ")" }; /** Sting: Space. */ static char str_space[] = { " " }; /** String: Wildcard. */ static char str_asterisk[] = { "*" }; /* @defgroup readauerrors [genau] Errors while reading. */ /*@{*/ /** Not enough memory. */ #define READAU_ERROR_NOT_ENOUGH_MEMORY 1 /** Section name not finished. */ #define READAU_ERROR_SECTION_NAME_UNFINISHED 2 /** Empty section name. */ #define READAU_ERROR_EMPTY_SECTION_NAME 3 /** Unknown section name. */ #define READAU_ERROR_UNKNOWN_SECTION_NAME 4 /** Missing section name. */ #define READAU_ERROR_SECTION_NAME_NEEDED 5 /** Incomplete input line. */ #define READAU_ERROR_LINE_INCOMPLETE 6 /** Missing numeric value. */ #define READAU_ERROR_NOT_A_NUMBER 7 /** State name already used. */ #define READAU_ERROR_STATE_ALREADY_EXISTS 8 /** Input name already used. */ #define READAU_ERROR_INPUT_ALREADY_EXISTS 9 /** Output name already used. */ #define READAU_ERROR_OUTPUT_ALREADY_EXISTS 10 /** There is already a rule defined for state/input combination. */ #define READAU_ERROR_GENERAL_RULE_ALREADY_DEFINED 11 /** There is already a rule defined for this input. */ #define READAU_ERROR_RULE_ALREADY_DEFINED_FOR_INPUT 12 /** Too many states. */ #define READAU_ERROR_TOO_MANY_STATES 13 /** Too many inputs. */ #define READAU_ERROR_TOO_MANY_INPUTS 14 /** Too many outputs. */ #define READAU_ERROR_TOO_MANY_OUTPUTS 15 /** Undefined input. */ #define READAU_ERROR_INPUT_UNDEFINED 16 /** Undefined output. */ #define READAU_ERROR_OUTPUT_UNDEFINED 17 /*@}*/ /** Delete an option. @param o Option to delete. */ static void delete_option DK_P1(au_option_line_t *, o) { char *ptr; if(o) { $? "= delete_option %lu %s", o->lineno, TR_STR(o->line) ptr = o->line; if(ptr) { dk_delete(ptr); } o->line = NULL; o->lineno = 0UL; dk_delete(o); } } /** Create new option. @param l Option line text. @param ln Line number of definition. @return Pointer to new option on success, NULL on error. */ static au_option_line_t * new_option DK_P2(char *, l, unsigned long, ln) { au_option_line_t *back = NULL; $? "+ new_option %s %lu", TR_STR(l), ln back = dk_new(au_option_line_t,1); if(back) { back->line = NULL; back->lineno = ln; back->line = dkstr_dup(l); if(!(back->line)) { delete_option(back); back = NULL; } } $? "- new_option %s", TR_PTR(back) return back; } /** Delete input, release memory. @param a Input to delete. */ static void delete_input DK_P1(au_input_t *, a) { char *ptr; if(a) { $? "= delete_input %s", TR_STR(a->name) ptr = a->name; if(ptr) { dk_delete(ptr); } a->name = NULL; a->number = 0; a->number_defined = 0; a->lineno = 0UL; dk_delete(a); } } /** Create new input. @param name Input name. @param l Line number of definition. @return Pointer to new input on success, NULL on error. */ static au_input_t * new_input DK_P2(char *, name, unsigned long, l) { au_input_t *back = NULL; $? "+ new_input %s %lu", TR_STR(name), l back = dk_new(au_input_t,1); if(back) { back->name = NULL; back->number = 0; back->number_defined = 0; back->lineno = l; back->name = dkstr_dup(name); if(!(back->name)) { delete_input(back); back = NULL; } } $? "- new_input %s", TR_PTR(back) return back; } /** Create new input and assign number. @param name Input name. @param l Line number of definition. @param num Input number. @return Pointer to new input on success, NULL on error. */ static au_input_t * new_input_number DK_P3(char *, name, unsigned long, l, int, num) { au_input_t *back = NULL; $? "+ new_input_number %s %lu %d", TR_STR(name), l, num back = new_input(name,l); if(back) { back->number = num; back->number_defined = 1; } $? "- new_input_number %s", TR_PTR(back) return back; } /** Delete output. @param a Output to delete. */ static void delete_output DK_P1(au_output_t *, a) { char *ptr; if(a) { $? "= delete_output %s", TR_STR(a->name) ptr = a->name; if(ptr) { dk_delete(ptr); } a->name = NULL; a->number = a->number_defined = 0; a->lineno = 0UL; dk_delete(a); } } /** Delete transition, release memory. @param t Transition to delete. */ static void delete_transition DK_P1(au_state_transition_t *, t) { char *ptr; if(t) { $? "= delete_transition %s %s %s %s", TR_STR(t->current_name), TR_STR(t->input_name), TR_STR(t->next_name), TR_STR(t->output_name) ptr = t->current_name; if(ptr) {dk_delete(ptr); } ptr = t->input_name; if(ptr) { dk_delete(ptr); } ptr = t->next_name; if(ptr) { dk_delete(ptr); } ptr = t->output_name; if(ptr) { dk_delete(ptr); } t->current_name = NULL; t->input_name = NULL; t->next_name = NULL; t->output_name = NULL; t->input_data = NULL; t->next_data = NULL; t->output_data = NULL; t->lineno = 0UL; dk_delete(t); } } /** Create new transition. @param c Current state name. @param i Input name. @param n Next state name. @param o Output name. @param l Line number of definition. @return Pointer to new transition on success, NULL on error. */ static au_state_transition_t * new_transition DK_P5(char *, c, char *, i, char *, n, char *, o, unsigned long, l) { au_state_transition_t *back = NULL; $? "+ new_transition %s %s %s %lu", TR_STR(i), TR_STR(n), TR_STR(o), l back = dk_new(au_state_transition_t,1); if(back) { back->current_name = dkstr_dup(c); back->current_data = NULL; back->input_name = dkstr_dup(i); back->input_data = NULL; back->next_name = dkstr_dup(n); back->next_data = NULL; back->output_name = dkstr_dup(o); back->output_data = NULL; back->lineno = l; if(!((back->current_name) && (back->input_name) && (back->next_name) && (back->output_name))) { delete_transition(back); back = NULL; } } $? "- new_transition %s", TR_PTR(back) return back; } /** Delete state (release memory). @param s State to delete. */ static void delete_state DK_P1(au_state_t *, s) { char *ptr; if(s) { $? "= delete_state %s", TR_STR(s->name) ptr = s->name; if(ptr) { dk_delete(ptr); } s->name = NULL; s->number = 0; s->number_defined = 0; if((s->trans) && (s->trit)) { dksto_it_close(s->trit); s->trit = NULL; } if(s->trans) { dksto_close(s->trans); s->trans = NULL; } dk_delete(s); } } /** Create new output. @param name Output name. @param l Line number of definition. @return Pointer to new output on success, NULL on error. */ static au_output_t * new_output DK_P2(char *, name, unsigned long, l) { au_output_t *back = NULL; $? "+ new_output %s %lu", TR_STR(name), l back = dk_new(au_output_t,1); if(back) { back->name = NULL; back->number = 0; back->number_defined = 0; back->lineno = l; back->name = dkstr_dup(name); if(!(back->name)) { delete_output(back); back = NULL; } } $? "- new_output %s", TR_PTR(back) return back; } /** Create new output and assign number. @param name Output name. @param l Line number of definition. @param num Output number. @return Pointer to new output on success, NULL on error. */ static au_output_t * new_output_number DK_P3(char *, name, unsigned long, l, int, num) { au_output_t *back = NULL; $? "+ new_output_number %s %lu %d", TR_STR(name), l, num back = new_output(name,l); if(back) { back->number = num; back->number_defined = 1; } $? "- new_output_number %s", TR_PTR(back) return back; } /** Compare two inputs by name. @param l Left input. @param r Right output or name text. @param cr Comparison criteria (0=input/input, 1=input/name). @return Comparison criteria. */ static int compare_inputs DK_P3(void *, l, void *, r, int, cr) { int back = 0; char *str; au_input_t *al, *ar; $? "+ compare_inputs %s %s %d", TR_PTR(l), TR_PTR(r), cr if(l) { if(r) { al = (au_input_t *)l; switch(cr) { case 1: { str = (char *)r; if(al->name) { back = strcmp(al->name, str); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = -1; } } break; default: { ar = (au_input_t *)r; if(al->name) { if(ar->name) { back = strcmp(al->name, ar->name); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = 1; } } else { if(ar->name) { back = -1; } } } break; } } else { back = 1; } } else { if(r) { back = -1; } } $? "- compare_inputs %d", back return back; } /** Compare outputs by name. @param l Left output. @param r Right output or name text. @param cr Comparison criteria (0=output/output, 1=output/name). @return Comparison result. */ static int compare_outputs DK_P3(void *, l, void *, r, int, cr) { int back = 0; char *str; au_output_t *al, *ar; $? "+ compare_outputs %s %s %d", TR_PTR(l), TR_PTR(r), cr if(l) { if(r) { al = (au_output_t *)l; switch(cr) { case 1: { str = (char *)r; if(al->name) { back = strcmp(al->name, str); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = -1; } } break; default: { ar = (au_output_t *)r; if(al->name) { if(ar->name) { back = strcmp(al->name, ar->name); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = 1; } } else { if(ar->name) { back = -1; } } } break; } } else { back = 1; } } else { if(r) { back = -1; } } $? "- compare_outputs %d", back return back; } /** Compare two states by name. @param l Left state. @param r Right state or name. @param cr Comparison criteria (0=state/state, 1=state/name). @return Comparison result. */ static int compare_states DK_P3(void *, l, void *, r, int, cr) { int back = 0; char *str; au_state_t *al, *ar; $? "+ compare_states %s %s %d", TR_PTR(l), TR_PTR(r), cr if(l) { if(r) { al = (au_state_t *)l; switch(cr) { case 1: { str = (char *)r; if(al->name) { back = strcmp(al->name, str); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = -1; } } break; default: { ar = (au_state_t *)r; if(al->name) { if(ar->name) { back = strcmp(al->name, ar->name); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = 1; } } else { if(ar->name) { back = -1; } } } break; } } else { back = 1; } } else { if(r) { back = -1; } } $? "- compare_states %d", back return back; } /** Compare two option lines by line number. @param l Left option line. @param r Right option line. @param crit Comparison criteria (ignored). @return Comparison result. */ static int compare_option_line DK_P3(void *, l, void *, r, int, crit) { int back = 0; au_option_line_t *ol, *or; $? "+ compare_option_line %s %s %d", TR_PTR(l), TR_PTR(r), crit if(l) { if(r) { ol = (au_option_line_t *)l; or = (au_option_line_t *)r; if(ol->lineno > or->lineno) back = 1; if(ol->lineno < or->lineno) back = -1; } else { back = 1; } } else { if(r) { back = -1; } } $? "- compare_option_line %d", back return back; } /** Compare two state transitions. @param l Left transition rule. @param r Right transition rule. @param cr Comparison criteria (0=line number, 1=transition by name/transition by name, 2=transition by name/name string). @return Comparison result. */ static int compare_transitions DK_P3(void *, l, void *, r, int, cr) { int back = 0; au_state_transition_t *tl, *tr; char *str; $? "+ compare_transitions %s %s %d", TR_PTR(l), TR_PTR(r), cr if(l) { if(r) { tl = (au_state_transition_t *)l; tr = (au_state_transition_t *)r; switch(cr) { case 1: { if(tl->input_name) { if(tr->input_name) { back = strcmp(tl->input_name, tr->input_name); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = 1; } } else { if(tr->input_name) { back = -1; } } } break; case 2: { str = (char *)r; if(tl->input_name) { back = strcmp(tl->input_name, str); if(back < 0) back = -1; if(back > 0) back = 1; } else { back = -1; } } break; default: { if(tl->lineno > tr->lineno) back = 1; if(tl->lineno < tr->lineno) back = -1; } break; } } else { back = 1; } } else { if(r) { back = -1; } } $? "- compare_transitions %d", back return back; } /** Create new state entry. @param n State name. @param l Line number of definition. @return Pointer to new state entry on success, NULL on error. */ static au_state_t * new_state DK_P2(char *, n, unsigned long, l) { au_state_t *back = NULL; $? "+ new_state %s %lu", TR_STR(n), l back = dk_new(au_state_t,1); if(back) { back->name = dkstr_dup(n); back->number = 0; back->number_defined = 0; back->lineno = l; back->trans = dksto_open(0); back->compat = NULL; if(back->trans) { dksto_set_comp(back->trans, compare_transitions, 1); back->trit = dksto_it_open(back->trans); } else { back->trit = NULL; } if(!((back->name) && (back->trans) && (back->trit))) { delete_state(back); back = NULL; } } $? "- new_state %s", TR_PTR(back) return back; } /** Create new numbered state entry. @param n State name. @param l Line number of state definition. @param num State number. @return Pointer to new entry on success, NULL on error. */ static au_state_t * new_state_number DK_P3(char *, n, unsigned long, l, int, num) { au_state_t *back = NULL; $? "+ new_state_number %s %lu %d", TR_STR(n), l, num back = new_state(n,l); if(back) { back->number = num; back->number_defined = 1; } $? "- new_state_number %s", TR_PTR(back) return back; } void readau_delete DK_P1(automata_t *, a) { au_option_line_t *ol; au_state_t *st; au_input_t *in; au_output_t *out; au_state_transition_t *tr; $? "+ readau_delete %s", TR_PTR(a) if(a) { if(a->asttrl) { if(a->asttrlit) { $? ". release asterisk transition name by line number" dksto_it_close(a->asttrlit); a->asttrlit = NULL; } dksto_close(a->asttrl); a->asttrl = NULL; } if(a->asttr) { if(a->asttrit) { $? ". release asterisk transition data by name" dksto_it_close(a->asttrit); a->asttrit = NULL; } dksto_close(a->asttr); a->asttr = NULL; } if(a->alltr) { if(a->alltrit) { $? ". release transition data" dksto_it_reset(a->alltrit); while((tr = (au_state_transition_t *)dksto_it_next(a->alltrit)) != NULL) { delete_transition(tr); } dksto_it_close(a->alltrit); a->alltrit = NULL; } dksto_close(a->alltr); a->alltr = NULL; } if(a->out) { if(a->outit) { $? ". release output data" dksto_it_reset(a->outit); while((out = (au_output_t *)dksto_it_next(a->outit)) != NULL) { delete_output(out); } dksto_it_close(a->outit); a->outit = NULL; } dksto_close(a->out); a->out = NULL; } if(a->in) { if(a->init) { $? ". release input data" dksto_it_reset(a->init); while((in = (au_input_t *)dksto_it_next(a->init)) != NULL) { delete_input(in); } dksto_it_close(a->init); a->init = NULL; } dksto_close(a->in); a->in = NULL; } if(a->st) { if(a->stit) { $? ". release state data" dksto_it_reset(a->stit); while((st = (au_state_t *)dksto_it_next(a->stit)) != NULL) { delete_state(st); } dksto_it_close(a->stit); a->stit = NULL; } dksto_close(a->st); a->st = NULL; } if(a->opt) { if(a->optit) { $? ". release option lines" dksto_it_reset(a->optit); while((ol = (au_option_line_t *)dksto_it_next(a->optit)) != NULL) { delete_option(ol); } dksto_it_close(a->optit); a->optit = NULL; } dksto_close(a->opt); a->opt = NULL; } a->general_rule = NULL; a->opt = NULL; a->optit = NULL; a->st = NULL; a->stit = NULL; a->in = NULL; a->init = NULL; a->out = NULL; a->outit = NULL; a->alltr = NULL; a->alltrit = NULL; a->general_rule = NULL; a->input_file_name = NULL; a->error_code = 0; dk_delete(a); } $? "- readau_delete" } /** Create new automata struct. @param flg Pointer to error code variable. @return Pointer to new automata on success, NULL on error. */ static automata_t * new_automata DK_P1(int *, flg) { automata_t *back = NULL; $? "+ new_automata" back = dk_new(automata_t,1); if(back) { back->h_file_name = NULL; back->initial_state = NULL; back->prototypes = 1; back->name_trans = NULL; back->name_res = NULL; back->i_prot = NULL; back->error_code = 0; back->opt = NULL; back->optit = NULL; back->st = NULL; back->stit = NULL; back->in = NULL; back->init = NULL; back->out = NULL; back->outit = NULL; back->alltr = NULL; back->alltrit = NULL; back->general_rule = NULL; back->def_output = NULL; back->doxy_output = 0; back->squeezed_output = 0; back->opt = dksto_open(0); if(back->opt) { dksto_set_comp(back->opt, compare_option_line, 0); back->optit = dksto_it_open(back->opt); if(!(back->optit)) back->error_code = 1; } else { back->error_code = 1; } back->st = dksto_open(0); if(back->st) { dksto_set_comp(back->st, compare_states, 0); back->stit = dksto_it_open(back->st); if(!(back->stit)) back->error_code = 1; } else { back->error_code = 1; } back->in = dksto_open(0); if(back->in) { dksto_set_comp(back->in, compare_inputs, 0); back->init = dksto_it_open(back->in); if(!(back->init)) back->error_code = 1; } else { back->error_code = 1; } back->out = dksto_open(0); if(back->out) { dksto_set_comp(back->out, compare_outputs, 0); back->outit = dksto_it_open(back->out); if(!(back->outit)) back->error_code = 1; } else { back->error_code = 1; } back->alltr = dksto_open(0); if(back->alltr) { dksto_set_comp(back->alltr, compare_transitions, 0); back->alltrit = dksto_it_open(back->alltr); if(!(back->alltrit)) back->error_code = 1; } else { back->error_code = 1; } back->asttr = dksto_open(0); if(back->asttr) { dksto_set_comp(back->asttr, compare_transitions, 1); back->asttrit = dksto_it_open(back->asttr); if(!(back->asttrit)) back->error_code = 1; } else { back->error_code = 1; } back->asttrl = dksto_open(0); if(back->asttrl) { dksto_set_comp(back->asttrl, compare_transitions, 0); back->asttrlit = dksto_it_open(back->asttrl); if(!(back->asttrlit)) { back->error_code = 1; } } else { back->error_code = 1; } if(back->error_code) { *flg = back->error_code; readau_delete(back); back = NULL; } } else { *flg = 1; } $? "- new_automata %s", TR_PTR(back) return back; } /** Keyword "options". */ static char key_options[] = { "options" }; /** Keyword "states". */ static char key_states[] = { "states" }; /** Keyword "inputs". */ static char key_inputs[] = { "inputs" }; /** Keyword "outputs", */ static char key_outputs[] = { "outputs" }; /** Keyword "rules". */ static char key_rules[] = { "rules" }; /** Keyword "end". */ static char key_end[] = { "end" }; /** Keyword: Wildcard. */ static char key_all[] = { "*" }; /** Read automata description from stream. @param a Automata. */ static void read_from_stream DK_P1(automata_t *, a) { int can_continue, section_number, number; char *line, *ptr, *ptr2, *ptr3, *ptr4, *ptr5; au_option_line_t *ol; au_state_t *st; au_input_t *in; au_output_t *out; au_state_transition_t *tr; char errbuffer[32], *errmsgs[16], **allstrings; $? "+ read_from_stream %s", TR_PTR(a) allstrings = genau_strings(); line = dk_new(char,LINELENGTH); if(line) { a->lineno = 0UL; can_continue = 1; section_number = 0; while(can_continue && (!(a->error_code))) { if(dkstream_gets(a->is,line,LINELENGTH)) { a->lineno += 1UL; dkapp_set_source_lineno(a->app, a->lineno); ptr = dkstr_chr(line, '#'); if(ptr) { *ptr = '\0'; } ptr = dkstr_start(line, NULL); if(ptr) { dkstr_chomp(ptr, NULL); $? ". line %s", ptr if(*ptr == '[') { /* new section */ $? ". seems to be new section" ptr2 = dkstr_chr(ptr, ']'); if(ptr2) { *ptr2 = '\0'; ptr++; ptr = dkstr_start(ptr, NULL); if(ptr) { dkstr_chomp(ptr, NULL); section_number = 0; if(strcmp(ptr, key_options) == 0) { section_number = 1; } if(strcmp(ptr, key_states) == 0) { section_number = 2; } if(strcmp(ptr, key_inputs) == 0) { section_number = 3; } if(strcmp(ptr, key_outputs) == 0) { section_number = 4; } if(strcmp(ptr, key_rules) == 0) { section_number = 5; } if(strcmp(ptr, key_end) == 0) { section_number = 6; can_continue = 0; } if(section_number == 0) { a->error_code = READAU_ERROR_UNKNOWN_SECTION_NAME; errmsgs[0] = allstrings[21]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = str_space; if(ptr) { errmsgs[3] = ptr; } errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } } else { a->error_code = READAU_ERROR_EMPTY_SECTION_NAME; errmsgs[0] = allstrings[22]; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 1); } } else { a->error_code = READAU_ERROR_SECTION_NAME_UNFINISHED; $? ". no closing bracket" errmsgs[0] = allstrings[23]; $? ". string gefunden %s", TR_STR(errmsgs[0]) errmsgs[1] = str_space; $? ". space hinzugefuegt" errmsgs[2] = str_bropen; $? ". klammer wird geoeffent" errmsgs[3] = str_space; $? ". space hinzugefuegt" if(ptr) { errmsgs[3] = ptr; } $? ". ptr=\"%s\"", TR_STR(ptr) errmsgs[4] = str_brclose; $? ". klammer wurde geschlossen" dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } } else { /* no new section */ switch(section_number) { case 1: { /* options */ ol = new_option(ptr, a->lineno); if(ol) { if(!dksto_add(a->opt, (void *)ol)) { delete_option(ol); a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } break; case 2: { /* states */ ptr2 = dkstr_next(ptr, NULL); if(ptr2) { ptr3 = dkstr_next(ptr2, NULL); st = (au_state_t *)dksto_it_find_like(a->stit, (void *)ptr, 1); if(st) { /* 10 ERROR: state already exists */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[9]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_STATE_ALREADY_EXISTS; } else { if(sscanf(ptr2, "%d", &number) == 1) { st = new_state_number(ptr, a->lineno, number); if(st) { if(!dksto_add(a->st, (void *)st)) { delete_state(st); st = NULL; a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } else { if(!(a->initial_state)) { a->initial_state = st; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } else { /* 11 ERROR: Wrong state number */ allstrings = genau_strings(); if((a->app) && allstrings && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[10]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr2; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_NOT_A_NUMBER; } } } else { st = (au_state_t *)dksto_it_find_like(a->stit, (void *)ptr, 1); if(st) { /* 12 ERROR: state already exists */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[11]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_STATE_ALREADY_EXISTS; } else { st = new_state(ptr, a->lineno); if(st) { if(!dksto_add(a->st, (void *)st)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_state(st); st = NULL; } else { if(!(a->initial_state)) { a->initial_state = st; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } } } break; case 3: { /* inputs */ ptr2 = dkstr_next(ptr, NULL); if(ptr2) { ptr3 = dkstr_next(ptr2, NULL); if(sscanf(ptr2, "%d", &number) == 1) { in = (au_input_t *)dksto_it_find_like(a->init, ptr, 1); if(in) { /* 13 ERROR: Input already exists */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[12]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_INPUT_ALREADY_EXISTS; } else { in = new_input_number(ptr, a->lineno, number); if(in) { if(!dksto_add(a->in, (void *)in)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_input(in); in = NULL; } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } } else { /* 14 ERROR: Wrong input number */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[13]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr2; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_NOT_A_NUMBER; } } else { in = (au_input_t *)dksto_it_find_like(a->init, ptr, 1); if(in) { /* 13 ERROR: Input already exists */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[12]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_INPUT_ALREADY_EXISTS; } else { in = new_input(ptr, a->lineno); if(in) { if(!dksto_add(a->in, (void *)in)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_input(in); in = NULL; } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } } } break; case 4: { /* outputs */ ptr2 = dkstr_next(ptr, NULL); if(ptr2) { ptr3 = dkstr_next(ptr2, NULL); if(sscanf(ptr2, "%d", &number) == 1) { out = (au_output_t *)dksto_it_find_like(a->outit, ptr, 1); if(out) { /* 15 ERROR: output already exists */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[14]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } a->error_code = READAU_ERROR_OUTPUT_ALREADY_EXISTS; } else { out = new_output_number(ptr, a->lineno, number); if(out) { if(!dksto_add(a->out, (void *)out)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_output(out); out = NULL; } else { if(!(a->def_output)) { a->def_output = out; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } } else { a->error_code = READAU_ERROR_NOT_A_NUMBER; allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[13]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr2; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } /* 14 ERROR: Wrong input number */ } } else { out = (au_output_t *)dksto_it_find_like(a->outit, ptr, 1); if(out) { a->error_code = READAU_ERROR_OUTPUT_ALREADY_EXISTS; allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[14]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); } } else { out = new_output(ptr, a->lineno); if(out) { if(!dksto_add(a->out, (void *)out)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_output(out); out = NULL; } else { if(!(a->def_output)) { a->def_output = out; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } } } break; case 5: { /* rules */ ptr2 = dkstr_next(ptr, NULL); if(ptr2) { ptr3 = dkstr_next(ptr2, NULL); if(ptr3) { ptr4 = dkstr_next(ptr3, NULL); if(ptr4) { ptr5 = dkstr_next(ptr4, NULL); if(strcmp(ptr2, str_asterisk)) { if(!dksto_it_find_like(a->init, ptr2, 1)) { errmsgs[0] = allstrings[24]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr2; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_WARNING, errmsgs, 5); } } if(strcmp(ptr4, str_asterisk)) { if(!dksto_it_find_like(a->outit, ptr4, 1)) { errmsgs[0] = allstrings[25]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = ptr4; errmsgs[4] = str_brclose; dkapp_log_msg(a->app, DK_LOG_LEVEL_WARNING, errmsgs, 5); } } tr = new_transition(ptr,ptr2,ptr3,ptr4,a->lineno); if(tr) { if(!dksto_add(a->alltr, (void *)tr)) { delete_transition(tr); tr = NULL; a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } else { /* 16 */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[15]; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 1); } } } else { /* 16 */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[15]; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 1); } } } else { /* 16 */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", a->lineno); errmsgs[0] = allstrings[15]; dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 1); } } } break; default: { } break; } } } } else { can_continue = 0; } } dk_delete(line); dkapp_set_source_lineno(a->app, 0UL); } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } $? "- read_from_stream error_code=%d", a->error_code } /** Link data (for each transition rule find the numeric values for states, input and output). @param a Automata. */ static void link_data DK_P1(automata_t *, a) { au_state_t *st; au_input_t *in; au_output_t *out; au_state_transition_t *tr, *tr2; int can_continue; char errbuffer[32], *errmsgs[16], **allstrings; $? "+ link_data" dksto_it_reset(a->alltrit); can_continue = 1; while(can_continue && (!(a->error_code))) { tr = (au_state_transition_t *)dksto_it_next(a->alltrit); if(tr) { if(strcmp(tr->current_name, key_all)) { st = dksto_it_find_like(a->stit, (void *)(tr->current_name), 1); if(!st) { /* 17 Warning: state not yet defined */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", tr->lineno); errmsgs[0] = allstrings[16]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = tr->current_name; errmsgs[4] = str_brclose; dkapp_set_source_lineno(a->app, tr->lineno); dkapp_log_msg(a->app, DK_LOG_LEVEL_WARNING, errmsgs, 5); dkapp_set_source_lineno(a->app, 0UL); } st = new_state(tr->current_name, tr->lineno); if(st) { if(!dksto_add(a->st, (void *)st)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_state(st); st = NULL; } else { if(!(a->initial_state)) { a->initial_state = st; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } if(st) { tr2 = dksto_it_find_like(st->trit, (void *)tr, 1); if(tr2) { char linenobuffer[32]; a->error_code = READAU_ERROR_RULE_ALREADY_DEFINED_FOR_INPUT; allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(linenobuffer, "%lu", tr2->lineno); errmsgs[0] = allstrings[26]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = linenobuffer; errmsgs[4] = str_brclose; dkapp_set_source_lineno(a->app, tr->lineno); dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); dkapp_set_source_lineno(a->app, 0UL); } } else { if(dksto_add(st->trans, (void *)tr)) { tr->current_data = st; } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } } } else { if(strcmp(tr->input_name, key_all)) { tr2 = dksto_it_find_like(a->asttrit, (void *)tr, 1); if(!tr2) { if(!dksto_add(a->asttr, (void *)tr)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } if(!dksto_add(a->asttrl, (void *)tr)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } else { char linenobuffer[32]; a->error_code = READAU_ERROR_RULE_ALREADY_DEFINED_FOR_INPUT; allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(linenobuffer, "%lu", tr2->lineno); errmsgs[0] = allstrings[26]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = linenobuffer; errmsgs[4] = str_brclose; dkapp_set_source_lineno(a->app, tr->lineno); dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); dkapp_set_source_lineno(a->app, 0UL); } } } else { if(!(a->general_rule)) { a->general_rule = tr; } else { char linenobuffer[32]; a->error_code = READAU_ERROR_GENERAL_RULE_ALREADY_DEFINED; allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(linenobuffer, "%lu", (a->general_rule)->lineno); errmsgs[0] = allstrings[27]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = linenobuffer; errmsgs[4] = str_brclose; dkapp_set_source_lineno(a->app, tr->lineno); dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 5); dkapp_set_source_lineno(a->app, 0UL); } } } } if(!(a->error_code)) { if(strcmp(tr->next_name, key_all)) { st = dksto_it_find_like(a->stit, (void *)(tr->next_name), 1); if(!st) { /* 18 Warning: state undefined */ allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { sprintf(errbuffer, "%lu", tr->lineno); errmsgs[0] = allstrings[17]; errmsgs[1] = str_space; errmsgs[2] = str_bropen; errmsgs[3] = tr->next_name; errmsgs[4] = str_brclose; dkapp_set_source_lineno(a->app, tr->lineno); dkapp_log_msg(a->app, DK_LOG_LEVEL_WARNING, errmsgs, 5); dkapp_set_source_lineno(a->app, 0UL); } st = new_state(tr->next_name, tr->lineno); if(st) { if(!dksto_add(a->st, (void *)st)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_state(st); st = NULL; } else { if(!(a->initial_state)) { a->initial_state = st; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } if(st) { tr->next_data = st; } } } if(!(a->error_code)) { if(strcmp(tr->input_name, key_all)) { in = dksto_it_find_like(a->init, (void *)(tr->input_name), 1); if(!in) { in = new_input(tr->input_name, tr->lineno); if(in) { if(!dksto_add(a->in, (void *)in)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_input(in); in = NULL; } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } if(in) { tr->input_data = in; } } } if(!(a->error_code)) { if(strcmp(tr->output_name, key_all)) { out = dksto_it_find_like(a->outit, (void *)(tr->output_name), 1); if(!out) { out = new_output(tr->output_name, tr->lineno); if(out) { if(!dksto_add(a->out, (void *)out)) { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; delete_output(out); out = NULL; } else { if(!(a->def_output)) { a->def_output = out; } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } if(out) { tr->output_data = out; } } } } else { can_continue = 0; } } $? "- link_data, error_code=%d", a->error_code } #if DEBUG #define XPTR(x) (x ? "PTR" : "(NULL)") #define XSTR(x) (x ? x : "(NULL)") static void debug_print DK_P1(automata_t *, a) { au_option_line_t *ol; au_state_t *st; au_input_t *in; au_output_t *out; au_state_transition_t *tr, *tr2; printf("[options]\n"); dksto_it_reset(a->optit); while((ol = dksto_it_next(a->optit)) != NULL) { printf("\t%s\n", XSTR(ol->line)); } printf("[inputs]\n"); dksto_it_reset(a->init); while((in = dksto_it_next(a->init)) != NULL) { printf("\t%s # %d\n", XSTR(in->name), in->number); } printf("[outputs]\n"); dksto_it_reset(a->outit); while((out = dksto_it_next(a->outit)) != NULL) { printf("\t%s # %d\n", XSTR(out->name), out->number); } printf("[states]\n"); dksto_it_reset(a->stit); while((st = dksto_it_next(a->stit)) != NULL) { printf("\t%s # %d\n", XSTR(st->name), st->number); dksto_it_reset(st->trit); while((tr = dksto_it_next(st->trit)) != NULL) { printf("\t# %s:%s %s:%s %s:%s %s:%s\n", XPTR(tr->current_data), XSTR(tr->current_name), XPTR(tr->input_data), XSTR(tr->input_name), XPTR(tr->next_data), XSTR(tr->next_name), XPTR(tr->output_data), XSTR(tr->output_name) ); } } printf("# General rule\n"); tr = a->general_rule; if(tr) { printf("\t# %s:%s %s:%s %s:%s %s:%s\n", XPTR(tr->current_data), XSTR(tr->current_name), XPTR(tr->input_data), XSTR(tr->input_name), XPTR(tr->next_data), XSTR(tr->next_name), XPTR(tr->output_data), XSTR(tr->output_name) ); } printf("# Rules for inputs by name\n"); dksto_it_reset(a->asttrit); while((tr = dksto_it_next(a->asttrit)) != NULL) { printf("\t# %s:%s %s:%s %s:%s %s:%s\n", XPTR(tr->current_data), XSTR(tr->current_name), XPTR(tr->input_data), XSTR(tr->input_name), XPTR(tr->next_data), XSTR(tr->next_name), XPTR(tr->output_data), XSTR(tr->output_name) ); } printf("# Rules for inputs by line number\n"); dksto_it_reset(a->asttrlit); while((tr = dksto_it_next(a->asttrlit)) != NULL) { printf("\t# %s:%s %s:%s %s:%s %s:%s\n", XPTR(tr->current_data), XSTR(tr->current_name), XPTR(tr->input_data), XSTR(tr->input_name), XPTR(tr->next_data), XSTR(tr->next_name), XPTR(tr->output_data), XSTR(tr->output_name) ); } printf("[rules]\n"); dksto_it_reset(a->alltrit); while((tr = dksto_it_next(a->alltrit)) != NULL) { printf("\t%s %s %s %s # %s %s %s %s\n", XSTR(tr->current_name), XSTR(tr->input_name), XSTR(tr->next_name), XSTR(tr->output_name), XPTR(tr->current_data), XPTR(tr->input_data), XPTR(tr->next_data), XPTR(tr->output_data) ); } } #endif /** Issue error "too many states". @param a Automata */ static void error_too_many_states DK_P1(automata_t *, a) { char **allstrings; char *errmsgs[16]; allstrings = genau_strings(); if(allstrings && (a->app) && (a->input_file_name)) { errmsgs[0] = allstrings[28]; dkapp_set_source_lineno(a->app, 0UL); dkapp_log_msg(a->app, DK_LOG_LEVEL_ERROR, errmsgs, 1); } } /** Assign numbers to states, inputs and outputs. @param a Automata. */ static void set_numbers DK_P1(automata_t *, a) { dk_bitfield_t *bf; au_state_t *st; au_input_t *in; au_output_t *out; int have_numbered, have_unnumbered, min, max; int direction, value, not_found; $? "+ set_numbers" /* States */ have_numbered = 0; have_unnumbered = 0; min = 0; max = 0; dksto_it_reset(a->stit); while((st = (au_state_t *)dksto_it_next(a->stit)) != NULL) { if(st->number_defined) { $? ". this state is numbered" if(have_numbered) { $? ". this is the first numbered state" if(min > (st->number)) min = st->number; if(max < (st->number)) max = st->number; } else { $? ". we already had numbered states" min = max = st->number; } have_numbered = 1; } else { have_unnumbered = 1; } } if(have_unnumbered) { $? ". we have unnumbered states" bf = NULL; direction = 1; value = -1; if(have_numbered) { $? ". some states are numbered" direction = 0; value = min; $? ". try to obtain bitfield %d %d", min, max bf = dkbf_open(1+max-min); if(bf) { $? ". obtained bitfield" dksto_it_reset(a->stit); while((st = (au_state_t *)dksto_it_next(a->stit)) != NULL) { if(st->number_defined) { dkbf_set(bf,((st->number)-min),1); } } } else { $? "! not enough memory" a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } dksto_it_reset(a->stit); while((st = (au_state_t *)dksto_it_next(a->stit)) != NULL) { if(!(st->number_defined)) { $? ". must set number for %s", st->name not_found = 1; if(not_found) { if(direction == 0) { if(bf) { while(not_found && (value < max)) { if(!dkbf_get(bf,(value-min))) { not_found = 0; dkbf_set(bf,(value-min),1); } else { value++; } } if(value == max) { direction = 1; } } else { value = max ; direction = 1; } } } if(not_found) { if(direction == 1) { if(value < DK_MAX_INT) { value++; not_found = 0; } else { if(have_numbered) { value = min; } else { value = 0; } direction = 2; } } } if(not_found) { if(direction == 2) { if(value > (0 - DK_MAX_INT)) { value--; not_found = 0; } else { } } } if(not_found) { a->error_code = READAU_ERROR_TOO_MANY_STATES; error_too_many_states(a); } $? ". value = %d", value st->number = value; /* st->number_defined = 1; */ } } if(bf) { dkbf_close(bf); } bf = NULL; } /* Inputs */ have_numbered = 0; have_unnumbered = 0; min = 0; max = 0; dksto_it_reset(a->init); while((in = (au_input_t *)dksto_it_next(a->init)) != NULL) { if(in->number_defined) { if(have_numbered) { if(min > (in->number)) min = in->number; if(max < (in->number)) max = in->number; } else { min = max = in->number; } have_numbered = 1; } else { have_unnumbered = 1; } } if(have_unnumbered) { bf = NULL; direction = 1; value = -1; if(have_numbered) { direction = 0; value = min; bf = dkbf_open(1+max-min); if(bf) { dksto_it_reset(a->init); while((in = (au_input_t *)dksto_it_next(a->init)) != NULL) { if(in->number_defined) { $? ". input %s uses number %d", in->name, in->number dkbf_set(bf,((in->number)-min),1); } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } $? ". numbered=%d unnumbered=%d min=%d max=%d", have_numbered, have_unnumbered, min, max dksto_it_reset(a->init); while((in = (au_input_t *)dksto_it_next(a->init)) != NULL) { $? ". checking %s", in->name if(!(in->number_defined)) { $? ". must set number for %s", in->name not_found = 1; if(not_found) { if(direction == 0) { if(bf) { while(not_found && (value < max)) { if(!dkbf_get(bf,(value-min))) { not_found = 0; dkbf_set(bf,(value-min),1); } else { value++; } } if(value == max) { direction = 1; } } else { value = max ; direction = 1; } } } if(not_found) { if(direction == 1) { if(value < DK_MAX_INT) { value++; not_found = 0; } else { if(have_numbered) { value = min; } else { value = 0; } direction = 2; } } } if(not_found) { if(direction == 2) { if(value > (0 - DK_MAX_INT)) { value--; not_found = 0; } else { } } } if(not_found) { a->error_code = READAU_ERROR_TOO_MANY_STATES; error_too_many_states(a); } $? ". value %d", value in->number = value; /* in->number_defined = 1; */ } } if(bf) { dkbf_close(bf); } bf = NULL; } /* Outputs */ have_numbered = 0; have_unnumbered = 0; min = 0; max = 0; dksto_it_reset(a->outit); while((out = (au_output_t *)dksto_it_next(a->outit)) != NULL) { if(out->number_defined) { if(have_numbered) { if(min > (out->number)) min = out->number; if(max < (out->number)) max = out->number; } else { min = max = out->number; } have_numbered = 1; } else { have_unnumbered = 1; } } if(have_unnumbered) { bf = NULL; direction = 1; value = -1; if(have_numbered) { direction = 0; value = min; bf = dkbf_open(1+max-min); if(bf) { dksto_it_reset(a->outit); while((out = (au_output_t *)dksto_it_next(a->outit)) != NULL) { if(out->number_defined) { dkbf_set(bf,((out->number)-min),1); } } } else { a->error_code = READAU_ERROR_NOT_ENOUGH_MEMORY; } } dksto_it_reset(a->outit); while((out = (au_output_t *)dksto_it_next(a->outit)) != NULL) { if(!(out->number_defined)) { not_found = 1; if(not_found) { if(direction == 0) { if(bf) { while(not_found && (value < max)) { if(!dkbf_get(bf,(value-min))) { not_found = 0; dkbf_set(bf,(value-min),1); } else { value++; } } if(value == max) { direction = 1; } } else { value = max ; direction = 1; } } } if(not_found) { if(direction == 1) { if(value < DK_MAX_INT) { value++; not_found = 0; } else { if(have_numbered) { value = min; } else { value = 0; } direction = 2; } } } if(not_found) { if(direction == 2) { if(value > (0 - DK_MAX_INT)) { value--; not_found = 0; } else { } } } if(not_found) { a->error_code = READAU_ERROR_TOO_MANY_STATES; error_too_many_states(a); } out->number = value; /* out->number_defined = 1; */ } } if(bf) { dkbf_close(bf); } bf = NULL; } $? "- set_numbers" } automata_t * readau_new DK_P4(dk_stream_t *, i, dk_app_t *, app, int *, flg, char *, name) { automata_t *back = NULL; char *errmsgs[32], **allstrings; if(i && flg) { back = new_automata(flg); if(back) { back->input_file_name = name; back->app = app; back->is = i; read_from_stream(back); if(!back->error_code) { link_data(back); if(!(back->error_code)) { set_numbers(back); if(!(back->error_code)) { #if DEBUG debug_print(back); #endif } } } if(back->error_code) { if((back->error_code) == READAU_ERROR_NOT_ENOUGH_MEMORY) { allstrings = genau_strings(); if(allstrings && (back->app) && (back->input_file_name)) { errmsgs[0] = allstrings[20]; dkapp_log_msg(back->app, DK_LOG_LEVEL_ERROR, errmsgs, 1); } } *flg = back->error_code; readau_delete(back); back = NULL; } } } return back; }