/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: dkct-au.ctr
*/

/*
Copyright (C) 2011-2013, Dirk Krause

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 author 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 dkct-au.c The dkct-au module.
*/


#line 10 "dkct-au.ctr"


#if DK3_USE_WX
#include "dkwxtrace.h"
#else
#include "dkct.h"
#endif




#line 20 "dkct-au.ctr"



/**	Sort criteria:Sort by state and input.
*/
#define DKCT_AU_RULE_SORT_STATE_INPUT	1

/**	Sort criteria: Inverted search order.
*/
#define DKCT_AU_RULE_SORT_REVERSE	2



/**	Input file section for options.
*/
#define	DKCT_AU_SECTION_OPTIONS		0

/**	Input file section for states.
*/
#define	DKCT_AU_SECTION_STATES		1

/**	Input file section for inputs.
*/
#define	DKCT_AU_SECTION_INPUTS		2

/**	Input file section for outputs.
*/
#define	DKCT_AU_SECTION_OUTPUTS		3

/**	Input file section for rules.
*/
#define	DKCT_AU_SECTION_RULES		4



/**	Section names.
*/
static char const * const dkct_au_section_names[] = {
/* 0 */ "options",
/* 1 */ "states",
/* 2 */ "inputs",
/* 3 */ "outputs",
/* 4 */ "rules",
/* 5 */ "option",
/* 6 */ "state",
/* 7 */ "input",
/* 8 */ "output",
/* 9 */ "rule",
NULL
};



/**	Keywords used by the module.
*/
static char const * const dkct_au_kw8[] = {
/*  0 */ "*",
/*  1 */ "\n",
/*  2 */ " ",
/*  3 */ "#ifndef ",
/*  4 */ "#else\n",
/*  5 */ "#endif\n\n",
/*  6 */ "#define ",
/*  7 */ "#error \"Redefinition of ",
/*  8 */ "\"\n",
/*  9 */ " %d\n",
/* 10 */ " (%d)\n",
/* 11 */ "/** ",
/* 12 */ " */\n",
/* 13 */ "State: ",
/* 14 */ "State machine input: ",
/* 15 */ "State machine output: ",
/* 16 */ "state_machine_%lu",
/* 17 */ "/** @defgroup dkct_state_machine_",
/* 18 */ " The ",
/* 19 */ " state machine. */\n/**@{*/\n\n",
/* 20 */ "/**@}*/\n\n",
/* 21 */ "#ifdef __cplusplus\nextern \"C\" { \n#endif\n\n",
/* 22 */ "#ifdef __cplusplus\n}\n#endif\n\n",
/* 23 */ "/**\tReset ",
/* 24 */ " state machine.\n",
/* 25 */ "\t@param\tst\tPointer to state variable.\n*/\n",
/* 26 */ "void ",
/* 27 */ "_reset(int *st);\n\n",
/* 28 */ "/**\tState machine ",
/* 29 */ " step.\n\t@param\tst\tPointer to state variable.\n",
/* 30 */ "\t@param\tin\tInput.\n\t@return\tTransition output.\n*/\n",
/* 31 */ "_step(int *st, int in);\n\n",
/* 32 */ "static\n",
/* 33 */ "void\n",
/* 34 */ "_reset(int *st)\n{\n  if(st) { *st = ",
/* 35 */ "; }\n}\n\n",
/* 36 */ "0",
/* 37 */ "int\n",
/* 38 */ "_step(int *st, int in)\n{\n  int back = ",
/* 39 */ ";\n",
/* 40 */ "  if(st) {\n    int os;\n    int nf = 1;\n    int ns = ",
/* 41 */ "}\n\n",
/* 42 */ "  } else {\n",
/* 43 */ "  }\n",
/* 44 */ "    if(nf) {\n",
/* 45 */ "    }\n",
/* 46 */ "    os = *st;\n",
/* 47 */ "    switch(os) {\n",
/* 48 */ "      case ",
/* 49 */ ": {\n",
/* 50 */ "      } break;\n",
/* 51 */ "        switch(in) {\n",
/* 52 */ "        }\n",
/* 53 */ "          case ",
/* 54 */ ": {\n",
/* 55 */ " nf = 0;\n          } break;\n",
/* 56 */ "ns = ",
/* 57 */ "os",
/* 58 */ "; back = ",
/* 59 */ ";",
/* 60 */ "      if(",
/* 61 */ ") {\n",
/* 62 */ "\n      } else {\n",
/* 63 */ "      }\n",
/* 64 */ "os == ",
/* 65 */ "in == ",
/* 66 */ "fprintf(",
/* 67 */ ", \"+ ",
/* 68 */ "_step state=%d input=%d\\n\", ((st) ? *st : 0), in);\n",
/* 69 */ ", \"- ",
/* 70 */ ", L\"+ ",
/* 71 */ ", L\"- ",
/* 72 */ "fwprintf(",
/* 73 */ "\". rule: ",
/* 74 */ "\\n\"", /* UNUSED */
/* 75 */ "_step state=%d output=%d\\n\", ((st) ? *st : 0), back);\n",
/* 76 */ "  return back;\n",
/* 77 */ "    *st = ns;\n",
NULL
};



/**	Option names.
*/
static char const * const dkct_au_option_names[] = {
/*  0 */ "name",
/*  1 */ "write-header",
NULL
};



/**	Compare two entries by name.
	@param	l	Left entry.
	@param	r	Right entry.
	@param	cr	Comparison critieria (0=struct/struct, 1=struct/name).
	@return	Comparison result.
*/
static
int
dkct_au_entry_compare(void *l, void *r, int cr)
{
  int back = 0;
  DKCT_STM_ENTRY	*pl;	/* Left object pointer. */
  DKCT_STM_ENTRY	*pr;	/* Right object pointer. */
  if(l) {
    if(r) {
      pl = (DKCT_STM_ENTRY *)l;
      pr = (DKCT_STM_ENTRY *)r;
      switch(cr) {
        case 1: {
	  if(pl->name) {
	    back = dk3str_c8_cmp(pl->name, (char const *)r);
	  } else {
	    back = -1;
	  }
	} break;
	default: {
          if(pl->name) {
            if(pr->name) {
	      back = dk3str_c8_cmp(pl->name, pr->name);
	    } else {
	      back = 1;
	    }
          } else {
            if(pr->name) {
	      back = -1;
	    }
          }
	} break;
      }
    } else {
      back = 1;
    }
  } else {
    if(r) {
      back = -1;
    }
  }
  if(back < -1) back = -1;
  if(back >  1) back =  1;
  return back;
}



/**	Delete entry.
	@param	p	Entry to delete.
*/
static
void
dkct_au_entry_delete(DKCT_STM_ENTRY *p)
{
  if(p) {	

#line 231 "dkct-au.ctr"
    dk3_release(p->name)
    dk3_release(p->comment)
    p->lineno = 0UL; p->value = 0; p->flag = 0x00;
    dk3_delete(p)
  }
}



/**	Create entry.
	@param	name	Entry name.
	@param	comment	Comment.
	@param	lineno	Line number in source file.
	@param	value	Numeric value (if specified).
	@param	flag	Flag: Use value.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Pointer to new entry on success, NULL on error.
*/
DKCT_STM_ENTRY *
dkct_au_entry_new(
  char const	*name,
  char const	*comment,
  unsigned long lineno,
  int		value,
  int		flag,
  dk3_app_t	*app
)
{
  DKCT_STM_ENTRY *back = NULL;
  

#line 261 "dkct-au.ctr"
  if(name) {
    back = dk3_new_app(DKCT_STM_ENTRY,1,app);
    if(back) {
      back->flag = ((flag)? 0x01 : 0x00);
      back->value = value;
      back->lineno = lineno;
      back->name = dk3str_c8_dup_app(name,app);
      back->comment = NULL;
      if(back->name) {
        if(comment) {
	  back->comment = dk3str_c8_dup_app(comment,app);
	  if(!(back->comment)) {
	    dkct_au_entry_delete(back);
	    back = NULL;
	  }
	}
      } else {
        dkct_au_entry_delete(back);
	back = NULL;
      }
    }
  } 

#line 283 "dkct-au.ctr"
  return back;
}



/**	Compare two rules, either by state+input or by line number.
	@param	l	Left rule.
	@param	r	Right rule.
	@param	cr	Comparison criteria (0=line,
	DKCT_AU_RULE_SORT_STATE_INPUT=state+input).
	@return	Comparison result.
*/
static
int
dkct_au_rule_compare(void *l, void *r, int cr)
{
  int back = 0;
  DKCT_STM_RULE *pl;	/* Left rule pointer. */
  DKCT_STM_RULE *pr;	/* Right rule pointer. */
  if(l) {
    if(r) {
      pl = (DKCT_STM_RULE *)l;
      pr = (DKCT_STM_RULE *)r;
      switch(cr & (~(DKCT_AU_RULE_SORT_REVERSE))) {
        case DKCT_AU_RULE_SORT_STATE_INPUT: {
	  /*
	  	First sort by states.
	  */
	  if(pl->state) {
	    if(pr->state) {
	      if((pl->state)->name) {
	        if((pr->state)->name) {
		  back = dk3str_c8_cmp((pl->state)->name, (pr->state)->name);
		} else {
		  back = 1;
		}
	      } else {
	        if((pr->state)->name) {
		  back = -1;
		}
	      }
	    } else {
	      back = 1;
	    }
	  } else {
	    if(pr->state) {
	      back = -1;
	    }
	  }
	  /*
	  	For equal states sort by input.
	  */
	  if(back == 0) {
	    if(pl->input) {
	      if(pr->input) {
	        if((pl->input)->name) {
		  if((pr->input)->name) {
		    back = dk3str_c8_cmp((pl->input)->name, (pr->input)->name);
		  } else {
		    back = 1;
		  }
		} else {
		  if((pr->input)->name) {
		    back = -1;
		  }
		}
	      } else {
	        back = 1;
	      }
	    } else {
	      if(pr->input) {
	        back = -1;
	      }
	    }
	  }
	} break;
	default: {
	  /*
	  	Simply sort by line number.
	  */
	  if(pl->lineno > pr->lineno) { back = 1; }
	  else {
	    if(pl->lineno < pr->lineno) { back = -1; }
	  }
	} break;
      }
    } else {
      back = 1;
    }
  } else {
    if(r) {
      back = -1;
    }
  }
  if(back < -1) { back = -1; }
  if(back >  1) { back =  1; }
  if(cr & DKCT_AU_RULE_SORT_REVERSE) {
    switch(back) {
      case  1: { back = -1; } break;
      case -1: { back =  1; } break;
    }
  }
  return back;
}



/**	Delete rule.
	@param	rp	Rule to delete.
*/
void
dkct_au_rule_delete(DKCT_STM_RULE *rp)
{
  if(rp) { 

#line 397 "dkct-au.ctr"
    rp->state = NULL;
    rp->input = NULL;
    rp->newstate = NULL;
    rp->output = NULL;
    rp->lineno = 0UL;
    dk3_delete(rp)
  }
}



/**	Create rule.
	@param	os	Old state.
	@param	in	Input.
	@param	ns	New state.
	@param	out	Output.
	@param	lineno	Line number in source file.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Pointer to new element on success, NULL on error.
*/
DKCT_STM_RULE *
dkct_au_rule_new(
  DKCT_STM_ENTRY *os,
  DKCT_STM_ENTRY *in,
  DKCT_STM_ENTRY *ns,
  DKCT_STM_ENTRY *out,
  unsigned long	  lineno,
  dk3_app_t	 *app
)
{
  DKCT_STM_RULE *back = NULL;
  int ok = 1;			/* Flag: No errors occured. */
  

#line 430 "dkct-au.ctr"
  back = dk3_new_app(DKCT_STM_RULE,1,app);
  if(back) {
    back->state = os;
    back->input = in;
    back->newstate = ns;
    back->output = out;
    back->lineno = lineno;
    if(!(ok)) {
      dkct_au_rule_delete(back);
      back = NULL;
    }
  } 

#line 442 "dkct-au.ctr"
  return  back;
}



/**	Delete all rules in a storage.
	@param	s	Storage containing the rules.
	@param	i	Iterator for storage.
*/
static
void
dkct_au_stm_rules_delete(dk3_sto_t *s, dk3_sto_it_t *i)
{
  DKCT_STM_RULE	*r;			/* Current rule to delete. */
  

#line 457 "dkct-au.ctr"
  if(s) {
    if(i) {
      dk3sto_it_reset(i);
      while((r = (DKCT_STM_RULE *)dk3sto_it_next(i)) != NULL) {
        dkct_au_rule_delete(r);
      }
      dk3sto_it_close(i);
    }
    dk3sto_close(s);
  } 

#line 467 "dkct-au.ctr"
}



/**	Delete all entries in a storage.
	@param	s	Storage containing the entries.
	@param	i	Iterator for storage.
*/
static
void
dkct_au_stm_entries_delete(dk3_sto_t *s, dk3_sto_it_t *i)
{
  DKCT_STM_ENTRY *e;			/* Current entry to delete. */
  

#line 481 "dkct-au.ctr"
  if(s) {
    if(i) {
      dk3sto_it_reset(i);
      while((e = (DKCT_STM_ENTRY *)dk3sto_it_next(i)) != NULL) {
        dkct_au_entry_delete(e);
      }
      dk3sto_it_close(i);
    }
    dk3sto_close(s);
  } 

#line 491 "dkct-au.ctr"
}



/**	Delete a state machine description.
	@param	p	State machine to delete.
*/
void
dkct_au_stm_delete(DKCT_STM *p)
{
  

#line 502 "dkct-au.ctr"
  if(p) {
    dkct_au_stm_rules_delete(p->s_wildcard, p->i_wildcard);
    dkct_au_stm_rules_delete(p->s_exact, p->i_exact);
    dkct_au_stm_entries_delete(p->s_states, p->i_states);
    dkct_au_stm_entries_delete(p->s_inputs, p->i_inputs);
    dkct_au_stm_entries_delete(p->s_outputs, p->i_outputs);
    p->s_wildcard = NULL; p->i_wildcard = NULL;
    p->s_exact = NULL; p->i_exact = NULL;
    p->s_states = NULL; p->i_states = NULL;
    p->s_outputs = NULL; p->i_outputs = NULL;
    p->s_inputs = NULL; p->i_inputs = NULL;
    dk3_release(p->name)
    p->lineno = 0UL;
    p->wrh = 0;
    p->rs = NULL;
    p->ds = NULL;
    p->dout = NULL;
    p->lngr = 0UL;
    dk3_delete(p)
  } 

#line 522 "dkct-au.ctr"
}



/**	Create new state machine description.
	@param	lineno	Line number in source file.
	@param	app	Application structure for diagnostics, may be NULL.
	@return	Pointer to new structure on success, NULL on error.
*/
DKCT_STM *
dkct_au_stm_new(unsigned long lineno, dk3_app_t *app)
{
  DKCT_STM	*back	= NULL;
  int		ok 	= 0;	/* Flag: Successfully initialized. */
  

#line 537 "dkct-au.ctr"
  back = dk3_new_app(DKCT_STM,1,app);
  if(back) {
    back->s_wildcard = NULL; back->i_wildcard = NULL;
    back->s_exact = NULL; back->i_exact = NULL;
    back->s_states = NULL; back->i_states = NULL;
    back->s_outputs = NULL; back->i_outputs = NULL;
    back->s_inputs = NULL; back->i_inputs = NULL;
    back->name = NULL;
    back->lineno = lineno;
    back->wrh = 1;
    back->section = DKCT_AU_SECTION_OPTIONS;
    back->rs = NULL;
    back->ds = NULL;
    back->dout = NULL;
    back->lngr = 0UL;
    back->stmno = 0UL;
    back->s_states = dk3sto_open_app(app);
    back->s_inputs = dk3sto_open_app(app);
    back->s_outputs = dk3sto_open_app(app);
    back->s_exact = dk3sto_open_app(app);
    back->s_wildcard = dk3sto_open_app(app);
    if(back->s_states) { back->i_states = dk3sto_it_open(back->s_states); }
    if(back->s_inputs) { back->i_inputs = dk3sto_it_open(back->s_inputs); }
    if(back->s_outputs) { back->i_outputs = dk3sto_it_open(back->s_outputs); }
    if(back->s_exact) { back->i_exact = dk3sto_it_open(back->s_exact); }
    if(back->s_wildcard) { back->i_wildcard= dk3sto_it_open(back->s_wildcard); }
    if((back->s_states) && (back->s_inputs) && (back->s_outputs)) {
      dk3sto_set_comp(back->s_states, dkct_au_entry_compare, 0);
      dk3sto_set_comp(back->s_inputs, dkct_au_entry_compare, 0);
      dk3sto_set_comp(back->s_outputs, dkct_au_entry_compare, 0);
      if((back->s_exact) && (back->s_wildcard)) {
        dk3sto_set_comp(
	  back->s_exact, dkct_au_rule_compare, DKCT_AU_RULE_SORT_STATE_INPUT
	);
	dk3sto_set_comp(back->s_wildcard, dkct_au_rule_compare, 0);
        if((back->i_states) && (back->i_inputs) && (back->i_outputs)) {
	  if((back->i_exact) && (back->i_wildcard)) {
	    ok = 1;
	  }
	}
      }
    }
    if(!(ok)) {
      dkct_au_stm_delete(back);
      back = NULL;
    }
  } 

#line 584 "dkct-au.ctr"
  return back;
}



/**	Process one option line.
	@param	stm	State machine description.
	@param	psrc	Source structure.
	@param	line	Text line.
	@param	lineno	Line number of current line.
	@return	1 on success, 0 on error.
*/
static
int
dkct_au_add_option(
  DKCT_STM *stm, DKCT_SRC *psrc, char *line, unsigned long lineno
)
{
  int back = 0;
  char		*p1;	/* Key (option name). */
  char		*p2;	/* Value. */
  int		 ai;	/* Array index of option name. */
  

#line 607 "dkct-au.ctr"
  p1 = dk3str_c8_start(line, NULL);
  if(p1) {
    p2 = dk3str_c8_chr(p1, '=');
    if(p2) {
      *(p2++) = '\0';
      p2 = dk3str_c8_start(p2, NULL);
      if(p2) {
        dk3str_c8_normalize(p1, NULL, '-');
        ai = dk3str_c8_array_index(dkct_au_option_names, p1, 0);
	switch(ai) {
	  case 0: {		

#line 618 "dkct-au.ctr"
	    if(stm->name) {
	      /* Warning: Redefinition of name */
	      dkct_to_log_1(psrc, 1, DK3_LL_WARNING, 28);
	      dk3_release(stm->name)
	    }
	    stm->name = dk3str_c8_dup_app(p2, psrc->app);
	    if(stm->name) {
	      back = 1;
	    } else {
	      /* ERROR: Memory */
	      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 29);
	    }
	  } break;
	  case 1: {		

#line 632 "dkct-au.ctr"
	    if(dk3str_c8_is_bool(p2)) {
	      stm->wrh = (dk3str_c8_is_on(p2) ? 1 : 0);
	      back = 1;
	    } else {
	      /* ERROR: Syntax (not boolean)! */
	      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 30);
	    }
	  } break;
	  default: {
	    dkct_to_log_3(psrc, 1, DK3_LL_ERROR, 10, 11, p1);
	  } break;
	}
      } else {
        /* ERROR: No value. */
	dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 9);
      }
    } else {
      /* Syntax */
      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 9);
    }
  }
  

#line 654 "dkct-au.ctr"
  return back;
}



/**	Add an entry to storage.
	@param	stm		State machine description.
	@param	psrc		Source structure.
	@param	line		Input line to process.
	@param	co		Comment for entry.
	@param	lineno		Line number of input line.
	@param	storage		Storage for entry.
	@param	iterator	Iterator for storage.
	@param	tp		Entry type (0=state, 1=input, 2=output).
	@return	1 on success, 0 on error.

*/
static
int
dkct_au_add_entry(
  DKCT_STM *stm,
  DKCT_SRC *psrc,
  char *line,
  char *co,
  unsigned long lineno,
  dk3_sto_t	*storage,
  dk3_sto_it_t	*iterator,
  int tp
)
{
  int 			back	= 0;
  char			*nptr;		/* Entry name. */
  char			*vptr;		/* Value (if any). */
  DKCT_STM_ENTRY	*e;		/* New entry. */
  DKCT_STM_ENTRY	*ep;		/* Search result. */
  int		 	i;		/* Value (if defined). */
  int		 	f;		/* Flag: Value defined. */
  

#line 692 "dkct-au.ctr"
  nptr = vptr = NULL;
  i = f = 0;
  nptr = dk3str_c8_start(line, NULL);
  if(nptr) {
    vptr = dk3str_c8_next(nptr, NULL);
    back = 1;
    if(vptr) {
      if(sscanf(vptr, "%d", &i) == 1) {
        f = 1;
      } else {
        back = 0;
        /* ERROR: Syntax */
	dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 31);
      }
    }
    if(back) {
      back = 0;
      e = dkct_au_entry_new(
        nptr, co, lineno, i, f, psrc->app
      );
      if(e) {
        ep = (DKCT_STM_ENTRY *)dk3sto_it_find_like(iterator, (void *)e, 0);
	if(ep) {
	  /* ERROR: Redefinition */
	  dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 32);
	  dkct_au_entry_delete(e);
	} else {
	  if(dk3sto_add(storage, (void *)e)) {
	    back = 1;
	    switch(tp) {
	      case 0: {
	        /*
			First state is reset state.
		*/
	        if(!(stm->rs)) { stm->rs = e; }
		/*
			First state is general rule next state default.
		*/
	        if(!(stm->ds)) { stm->ds = e; }
	      } break;
	      case 2: {
	        /*
			First output is general rule output default.
		*/
	        if(!(stm->dout)) { stm->dout = e; }
	      } break;
	    }
	  } else {
	    dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
	    dkct_au_entry_delete(e);
	  }
	}
      } else {
        /* ERROR Memory */
	dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
      }
    }
  } else {
    /* ERROR: Syntax */
    dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 33);
  } 

#line 753 "dkct-au.ctr"
  return back;
}



/**	Find named entry in storage.
	@param	psrc	Source structure.
	@param	sto	Storage.
	@param	ist	Storage iterator.
	@param	name	Name of entry to find.
	@param	ok	Pointer to not-found-is-ok variable.
	@param	t	Type (0=state, 1=input, 2=output).
	@param	lineno	Line number.
	@return	Pointer to found entry on success, NULL on error.
*/
static
DKCT_STM_ENTRY *
dkct_au_find_entry(
  DKCT_SRC *psrc,
  dk3_sto_t *sto,
  dk3_sto_it_t *ist,
  char *name,
  unsigned long lineno,
  int *ok,
  int t
)
{
  DKCT_STM_ENTRY	*back = NULL;
  if(dk3str_c8_cmp(dkct_au_kw8[0], name) == 0) {
    *ok = 1;
  } else {
    back = (DKCT_STM_ENTRY *)dk3sto_it_find_like(ist, name, 1);
    if(!(back)) {
      /* Warning: State/input/output undeclared! */
      dkct_to_log_3(psrc, 1, DK3_LL_WARNING, 34, 35, name);
      back = dkct_au_entry_new(name, NULL, lineno, 0, 0, psrc->app);
      if(back) {
        if(!dk3sto_add(sto, (void *)back)) {
	  dkct_au_entry_delete(back);
	  back = NULL;
	}
      } else {
        /* ERROR: Failed to create entry! */
	dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 29);
      }
    }
  }
  return back;
}



/**	Add rule to state machine.
	@param	stm	State machine description.
	@param	psrc	Source structure.
	@param	line	Input line to process.
	@param	co	Comment for rule.
	@param	lineno	Current line number.
	@return	1 on success, 0 on error.
*/
static
int
dkct_au_add_rule(
  DKCT_STM *stm, DKCT_SRC *psrc, char *line, char *co, unsigned long lineno
)
{
  int back = 0;
  DKCT_STM_RULE		tr;		/* Test rul. */
  DKCT_STM_RULE		*nr;		/* New rule. */
  char			*p1;		/* Old state. */
  char			*p2;		/* Input. */
  char			*p3;		/* New state. */
  char			*p4;		/* Output. */
  DKCT_STM_ENTRY	*e1;		/* Old state. */
  DKCT_STM_ENTRY	*e2;		/* Input. */
  DKCT_STM_ENTRY	*e3;		/* New state. */
  DKCT_STM_ENTRY	*e4;		/* Output. */
  int			ok1;		/* Flag: Old state *. */
  int			ok2;		/* Flag: Input *. */
  int			ok3;		/* Flag: New state *. */
  int			ok4;		/* Flag: Output *. */
  int			can_add;	/* Flag: Rule ok, add. */
  

#line 836 "dkct-au.ctr"
  e1 = e2 = e3 = e4 = NULL; ok1 = ok2 = ok3 = ok4 = 0;
  p1 = dk3str_c8_start(line, NULL);
  if(p1) {
    p2 = dk3str_c8_next(p1, NULL);
    if(p2) {
      p3 = dk3str_c8_next(p2, NULL);
      if(p3) {
        p4 = dk3str_c8_next(p3, NULL);
	if(p4) {
	  (void)dk3str_c8_next(p4, NULL);
	  e1 = dkct_au_find_entry(
	    psrc, stm->s_states, stm->i_states, p1, lineno, &ok1, 0
	  );
	  e2 = dkct_au_find_entry(
	    psrc, stm->s_inputs, stm->i_inputs, p2, lineno, &ok2, 1
	  );
	  e3 = dkct_au_find_entry(
	    psrc, stm->s_states, stm->i_states, p3, lineno, &ok3, 0
	  );
	  e4 = dkct_au_find_entry(
	    psrc, stm->s_outputs, stm->i_outputs, p4, lineno, &ok4, 2
	  );
	  if(
	    ((e1) || (ok1)) && ((e2) || (ok2))
	    && ((e3) || (ok3)) && ((e4) || (ok4))
	  )
	  {
	    can_add = 1;
	    tr.state = e1; tr.input = e2; tr.newstate = e3; tr.output = e4;
	    if((e1) && (e2)) {
	      DKCT_STM_RULE *xrp;
	      if((xrp = (DKCT_STM_RULE *)dk3sto_it_find_like(
	                   stm->i_exact, (void *)(&tr),
			   DKCT_AU_RULE_SORT_STATE_INPUT
	                )
	         ) != NULL
	        )
	      {
	        char	ulbuffer[32];
		sprintf(ulbuffer, "%lu", xrp->lineno);
	        can_add = 0;
		/* ERROR: Conflict! */
		dkct_to_log_3(psrc, 1, DK3_LL_ERROR, 36, 39, ulbuffer);
	      }
	    }
	    if(can_add) {
	      if((e1) && (e2)) {
	        nr = dkct_au_rule_new(e1, e2, e3, e4, lineno, psrc->app);
		if(nr) {
		  if(dk3sto_add(stm->s_exact, (void *)nr)) {
		    back = 1;
		  } else {
		    dkct_au_rule_delete(nr);
		    dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
		  }
		} else {
		  /* ERROR: Memory! */
		  dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
		}
	      } else {
	        if((e1) || (e2)) {
		  nr = dkct_au_rule_new(e1, e2, e3, e4, lineno, psrc->app);
		  if(nr) {
		    if(dk3sto_add(stm->s_wildcard, (void *)nr)) {
		      back = 1;
		    } else {
		      dkct_au_rule_delete(nr);
		      dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
		    }
		  } else {
		    /* ERROR: Memory! */
		    dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
		  }
		} else {
		  back = 1;
		  if(stm->lngr) {
		    char buffer[32];
		    sprintf(buffer, "%lu", stm->lngr);
		    /* Warning: General rule redefined! */
		    dkct_to_log_3(psrc, 1, DK3_LL_ERROR, 36, 39, buffer);
		  }
		  stm->ds = e3;
		  stm->dout = e4;
		  stm->lngr = lineno;
		}
	      }
	    }
	  } else {
	    dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 29);
	  }
	} else {
	  dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 33);
	}
      } else {
        dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 33);
      }
    } else {
      dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 33);
    }
  }
  

#line 937 "dkct-au.ctr"
  return back;
}



/**	Process one input line.
	@param	stm	State machine description.
	@param	psrc	Source structure.
	@param	line	Line to process.
	@param	lineno	Current line number.
	@return	1 on success, 0 on error.
*/
int
dkct_au_add_line(
  DKCT_STM *stm, DKCT_SRC *psrc, char *line, unsigned long lineno
)
{
  int back = 0;
  char		*lstart;	/* Start of input line. */
  char		*pc;		/* Comment pointer. */
  int		 ai;		/* Array index. */
  

#line 959 "dkct-au.ctr"
  if((stm) && (line)) {		

#line 960 "dkct-au.ctr"
    lstart = dk3str_c8_start(line, NULL);
    if(lstart) {		

#line 962 "dkct-au.ctr"
      pc = NULL;
      if(*lstart != '#') {	

#line 964 "dkct-au.ctr"
        if(*lstart == '[') {	

#line 965 "dkct-au.ctr"
	  lstart++;
	  lstart = dk3str_c8_start(lstart, NULL);
	  if(lstart) {
	    stm->section = -1;
	    pc = dk3str_c8_chr(lstart, ']');
	    if(pc) {
	      *pc = '\0';
	      dk3str_c8_chomp(lstart, NULL);	

#line 973 "dkct-au.ctr"
	      ai = dk3str_c8_array_index(dkct_au_section_names, lstart, 0);
	      

#line 975 "dkct-au.ctr"
	      switch(ai) {
	        case 0: case 5: {
	          stm->section = DKCT_AU_SECTION_OPTIONS; back = 1;
	        } break;
	        case 1: case 6: {
	          stm->section = DKCT_AU_SECTION_STATES; back = 1;
	        } break;
	        case 2: case 7: {
	          stm->section = DKCT_AU_SECTION_INPUTS; back = 1;
	        } break;
	        case 3: case 8: {
	          stm->section = DKCT_AU_SECTION_OUTPUTS; back = 1;
	        } break;
	        case 4: case 9: {
	          stm->section = DKCT_AU_SECTION_RULES; back = 1;
	        } break;
		default: {
		  dkct_to_log_3(psrc, 1, DK3_LL_ERROR, 99, 100, lstart);
		} break;
	      }
	    } else {
	      /* ERROR: Syntax! */
	      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 37);
	    }
	  } else {
	    dkct_to_log_1(psrc, 0, DK3_LL_ERROR, 37);
	  }
	} else {		

#line 1003 "dkct-au.ctr"
	  pc = dk3str_c8_chr(lstart, '#');
	  if(pc) { *(pc++) = '\0'; pc = dk3str_c8_start(pc, NULL); }
	  switch(stm->section) {
	    case DKCT_AU_SECTION_OPTIONS: {	

#line 1007 "dkct-au.ctr"
	      back = dkct_au_add_option(stm, psrc, lstart, lineno);
	    } break;
	    case DKCT_AU_SECTION_STATES: {	

#line 1010 "dkct-au.ctr"
              back = dkct_au_add_entry(
                stm, psrc, lstart, pc, lineno, stm->s_states, stm->i_states, 0
              );
	    } break;
	    case DKCT_AU_SECTION_INPUTS: {	

#line 1015 "dkct-au.ctr"
              back = dkct_au_add_entry(
                stm, psrc, lstart, pc, lineno, stm->s_inputs, stm->i_inputs, 1
              );
	    } break;
	    case DKCT_AU_SECTION_OUTPUTS: {	

#line 1020 "dkct-au.ctr"
              back = dkct_au_add_entry(
                stm, psrc, lstart, pc, lineno, stm->s_outputs, stm->i_outputs, 2
              );
	    } break;
	    case DKCT_AU_SECTION_RULES: {	

#line 1025 "dkct-au.ctr"
	      back = dkct_au_add_rule(stm, psrc, lstart, pc, lineno);
	    } break;
	  }
	}
      } else {
        back = 1;	/* comments ok */
      }
    } else {
      back = 1;		/* empty lines ok */
    }
  } 

#line 1036 "dkct-au.ctr"
  return back;
}



/**	Check whether there is at least one entry in the storage.
	@param	it	Iterator of storage to check.
	@return	1 on success, 0 on error (storage empty).
*/
static
int
dkct_au_stm_entries_check(dk3_sto_it_t *it)
{
  int back = 0;
  dk3sto_it_reset(it);
  if(dk3sto_it_next(it)) {
    back = 1;
  }
  return back;
}



/**	Assign values to state/input/output storage.
	@param	psrc	Source structure.
	@param	stm	State machine to modify.
	@param	it	Iterator for state/input/output storage.
	@return	1 on success, 0 on error.
*/
static
int
dkct_au_set_values(DKCT_SRC *psrc, DKCT_STM *stm, dk3_sto_it_t *it)
{
  int			back		= 1;	
  DKCT_STM_ENTRY	*ep		= NULL;	/* Current entry to process. */
  dk3_bf_t		*bf		= NULL;	/* Bit field, used values. */
  int			min		= 0;	/* Minimum value so far. */
  int			max		= 0;	/* Maximum value so far. */
  int			valfound	= 0;	/* Flag: Values specified. */
  int			cv		= 0;	/* Current value. */
  int			cc		= 0;	/* Flag: Continue search. */
  

#line 1078 "dkct-au.ctr"
  dk3sto_it_reset(it);
  while((ep = (DKCT_STM_ENTRY *)dk3sto_it_next(it)) != NULL) {
    if(ep->flag) {	

#line 1081 "dkct-au.ctr"
      if(valfound) {	

#line 1082 "dkct-au.ctr"
        if(ep->value < min) min = ep->value;
	if(ep->value > max) max = ep->value;
      } else {		

#line 1085 "dkct-au.ctr"
        min = max = ep->value;
      }
      valfound = 1;
    } else {		

#line 1089 "dkct-au.ctr"
    }
  }
  if(valfound) {	

#line 1092 "dkct-au.ctr"
    bf = dk3bf_open_app((max - min + 1), psrc->app);
    if(bf) {
      /*
      	Find used values.
      */
      dk3sto_it_reset(it);
      while((ep = (DKCT_STM_ENTRY *)dk3sto_it_next(it)) != NULL) {
        if(ep->flag) {
	  dk3bf_set(bf, (ep->value - min), 1);
	}
      }
      /*
      	Set missing values.
      */
      cv = 0;
      dk3sto_it_reset(it);
      while((ep = (DKCT_STM_ENTRY *)dk3sto_it_next(it)) != NULL) {
        if(!(ep->flag)) {
	  do {			

#line 1111 "dkct-au.ctr"
	    cc = 0;
	    if((cv >= min) && (cv <= max)) {
	      if(dk3bf_get(bf, (cv - min))) {
	        cc = 1;		

#line 1115 "dkct-au.ctr"
		cv++;
		if(cv == 0) {	

#line 1117 "dkct-au.ctr"
		  cc = 0;
		  back = 0;
		  /* ERROR: Overflow */
		  dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 38);
		}
	      }
	    }
	  } while(cc);
	  cc = 0;
	  if((cv >= min) && (cv <= max)) {
	    if(!dk3bf_get(bf, (cv - min))) {
	      cc = 1;
	    }
	  } else {
	    cc = 1;
	  }
	  if(cc) {		

#line 1134 "dkct-au.ctr"
	    ep->value = cv++;
	    if(cv == 0) {	

#line 1136 "dkct-au.ctr"
	      back = 0;
	      /* ERROR: Overflow */
	      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 38);
	    }
	  }
	}
      }
      dk3bf_close(bf);
    } else {		

#line 1145 "dkct-au.ctr"
      back = 0;
      /* ERROR: Memory */
      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 29);
    }
  } else {		

#line 1150 "dkct-au.ctr"
    cv = 0;
    dk3sto_it_reset(it);
    while((ep = (DKCT_STM_ENTRY *)dk3sto_it_next(it)) != NULL) {
      ep->value = cv++;
      if(cv == 0) {	

#line 1155 "dkct-au.ctr"
        back = 0;
	/* ERROR: Overflow */
	dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 38);
      }
    }
  } 

#line 1161 "dkct-au.ctr"
  return back;
}



int
dkct_au_stm_check(DKCT_SRC *psrc, DKCT_STM *stm)
{
  int back = 0;
  int	sfound = 0;	/* Number of states found. */
  int	ifound = 0;	/* Number of inputs found. */
  int	ofound = 0;	/* Number of outputs found. */

  dk3app_set_source_line(psrc->app, stm->lineno);
  sfound = dkct_au_stm_entries_check(stm->i_states);
  ifound = dkct_au_stm_entries_check(stm->i_inputs);
  ofound = dkct_au_stm_entries_check(stm->i_outputs);
  if((sfound) && (ifound) && (ofound)) {
    back = 1;
    if(!dkct_au_set_values(psrc, stm, stm->i_states)) { back = 0; }
    if(!dkct_au_set_values(psrc, stm, stm->i_inputs)) { back = 0; }
    if(!dkct_au_set_values(psrc, stm, stm->i_outputs)) { back = 0; }
  } else {
    if(!(sfound)) {
      /* ERROR: No states declared! */
      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 40);
    }
    if(!(ifound)) {
      /* ERROR: No inputs declared! */
      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 41);
    }
    if(!(ofound)) {
      /* ERROR: No outputs declared! */
      dkct_to_log_1(psrc, 1, DK3_LL_ERROR, 42);
    }
  }
  return back;
}



/**	Write definition for one storage entry.
	@param	psrc	Source structure.
	@param	stm	State machine.
	@param	ep	Entry to write
	@param	commi	Keyword index for "state", "input", or "output".
*/
static
void
dkct_au_write_one_entry(
  DKCT_SRC *psrc, DKCT_STM *stm, DKCT_STM_ENTRY *ep, size_t commi
)
{
  

#line 1215 "dkct-au.ctr"
  fputs(dkct_au_kw8[3], psrc->fipo);
  fputs(ep->name, psrc->fipo);
  fputs(dkct_au_kw8[1], psrc->fipo);
  fputs(dkct_au_kw8[11], psrc->fipo);
  fputs(dkct_au_kw8[commi], psrc->fipo);
  if(ep->comment) {
    fputs(ep->comment, psrc->fipo);
  } else {
    fputs(ep->name, psrc->fipo);
  }
  fputs(dkct_au_kw8[12], psrc->fipo);
  if((psrc->dkcto).lnn) {
    psrc->lineno = ep->lineno;
    dkct_tr_show_source_line(psrc, 0);
  }
  fputs(dkct_au_kw8[6], psrc->fipo);
  fputs(ep->name, psrc->fipo);
  fprintf(psrc->fipo, dkct_au_kw8[(ep->value >= 0) ? 9 : 10], ep->value);
  fputs(dkct_au_kw8[4], psrc->fipo);		/* else */
  if((psrc->dkcto).lnn) {
    psrc->lineno = ep->lineno;
    dkct_tr_show_source_line(psrc, 0);
  }
  fputs(dkct_au_kw8[7], psrc->fipo);
  fputs(ep->name, psrc->fipo);
  fputs(dkct_au_kw8[8], psrc->fipo);
  fputs(dkct_au_kw8[5], psrc->fipo);		/* endif */
  

#line 1243 "dkct-au.ctr"
}



/**	Write all entries of a storage.
	@param	psrc	Source structure.
	@param	stm	State machine.
	@param	it	Storage iterator.
	@param	commi	Keyword index for "state", "input", or "output".
*/
static
void
dkct_au_write_entry_storage(
  DKCT_SRC *psrc, DKCT_STM *stm, dk3_sto_it_t *it, size_t commi
)
{
  DKCT_STM_ENTRY	*ep;	/* Current entry. */
  

#line 1261 "dkct-au.ctr"
  dk3sto_it_reset(it);
  while((ep = (DKCT_STM_ENTRY *)dk3sto_it_next(it)) != NULL) {
    dkct_au_write_one_entry(psrc, stm, ep, commi);
  } 

#line 1265 "dkct-au.ctr"
}



/**	Write state machine name to output file.
	@param	psrc	Source structure.
	@param	stm	State machine.
*/
static
void
dkct_au_write_stm_name(DKCT_SRC *psrc, DKCT_STM *stm)
{
  if(stm->name) {
    fputs(stm->name, psrc->fipo);
  } else {
    fprintf(psrc->fipo, dkct_au_kw8[16], stm->stmno);
  }
}



/**	Write state/input/output entry definitions.
	@param	psrc	Source structure.
	@param	stm	State machine.
*/
void
dkct_au_write_entries(DKCT_SRC *psrc, DKCT_STM *stm)
{
  /*
  	Begin doxygen group
  */
  fputs(dkct_au_kw8[17], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[18], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[19], psrc->fipo);
  /*
  	Write the entries
  */
  dkct_au_write_entry_storage(psrc, stm, stm->i_states, 13);
  dkct_au_write_entry_storage(psrc, stm, stm->i_inputs, 14);
  dkct_au_write_entry_storage(psrc, stm, stm->i_outputs, 15);
  /*
  	End doxygen group
  */
  fputs(dkct_au_kw8[20], psrc->fipo);
}



void
dkct_au_write_prototypes(DKCT_SRC *psrc, DKCT_STM *stm)
{
  fputs(dkct_au_kw8[21], psrc->fipo);
  fputs(dkct_au_kw8[23], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[24], psrc->fipo);
  fputs(dkct_au_kw8[25], psrc->fipo);
  fputs(dkct_au_kw8[26], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[27], psrc->fipo);
  fputs(dkct_au_kw8[28], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[29], psrc->fipo);
  fputs(dkct_au_kw8[30], psrc->fipo);
  fputs(dkct_au_kw8[37], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[31], psrc->fipo);
  fputs(dkct_au_kw8[22], psrc->fipo);
}



/**	Write a transition result.
	@param	psrc	Source structure.
	@param	stm	State machine.
	@param	rp	Rule.
	@param	indent	Level of indent.
*/
static
void
dkct_au_write_transition_result(
  DKCT_SRC *psrc, DKCT_STM *stm, DKCT_STM_RULE *rp, int indent
)
{
  int i;	/* Number of indent spaces already written. */
  /* DEBUG CODE IF -d */
  for(i = 0; i < indent; i++) { fputc(' ', psrc->fipo); }
  fputs(dkct_au_kw8[56], psrc->fipo);
  if(rp->newstate) {
    fputs((rp->newstate)->name, psrc->fipo);
  } else {
    fputs(dkct_au_kw8[57], psrc->fipo);
  }
  fputs(dkct_au_kw8[58], psrc->fipo);
  if(rp->output) {
    fputs((rp->output)->name, psrc->fipo);
  } else {
    if(stm->dout) {
      fputs((stm->dout)->name, psrc->fipo);
    } else {
      fputs(dkct_au_kw8[36], psrc->fipo);
    }
  }
  fputs(dkct_au_kw8[59], psrc->fipo);
}



/**	Create debug code for entering and leaving the
	transition function.
	@param	psrc	Source structure.
	@param	stm	State machine.
	@param	pos	Position (0=invokation, 1=return).
*/
static
void
dkct_au_debug_transition(DKCT_SRC *psrc, DKCT_STM *stm, int pos)
{
  char const *fnptr;	/* Debug output file. */

  fnptr = dkct_tr_get_kw8(((psrc->dkcto).deb == 2) ? 28 : 29);
  fputs(dkct_tr_get_kw8(67), psrc->fipo);
  if((psrc->dkcto).win) {
    fputs(dkct_tr_get_kw8(21), psrc->fipo);
    /* char 16 start */
    psrc->lineno = stm->lineno;
    fputs(dkct_tr_get_kw8(61), psrc->fipo);
    dkct_tr_show_filename_and_lineno(psrc);
    fputs(dkct_tr_get_kw8(35), psrc->fipo);
    fputs(fnptr, psrc->fipo);
    fputs(dkct_tr_get_kw8(34), psrc->fipo);

    fputs(dkct_au_kw8[72], psrc->fipo);
    fputs(fnptr, psrc->fipo);
    fputs(dkct_au_kw8[(pos == 1) ? 71 : 70], psrc->fipo);
    dkct_au_write_stm_name(psrc, stm);
    fputs(dkct_au_kw8[(pos == 1) ? 75 : 68], psrc->fipo);

    fputs(dkct_tr_get_kw8(37), psrc->fipo);
    fputs(fnptr, psrc->fipo);
    fputs(dkct_tr_get_kw8(34), psrc->fipo);
    /* char 16 end */
    fputs(dkct_tr_get_kw8(22), psrc->fipo);
  }
  /* char 8 start */
  if((psrc->dkcto).deb == 1) {
    fputs(dkct_tr_get_kw8(30), psrc->fipo);
  }
  psrc->lineno = stm->lineno;
  fputs(dkct_tr_get_kw8(33), psrc->fipo);
  dkct_tr_show_filename_and_lineno(psrc);
  fputs(dkct_tr_get_kw8(35), psrc->fipo);
  fputs(fnptr, psrc->fipo);
  fputs(dkct_tr_get_kw8(34), psrc->fipo);

  fputs(dkct_au_kw8[66], psrc->fipo);
  fputs(fnptr, psrc->fipo);
  fputs(dkct_au_kw8[(pos == 1) ? 69 : 67], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[(pos == 1) ? 75 : 68], psrc->fipo);

  fputs(dkct_tr_get_kw8(37), psrc->fipo);
  fputs(fnptr, psrc->fipo);
  fputs(dkct_tr_get_kw8(34), psrc->fipo);
  if((psrc->dkcto).deb == 1) {
    fputs(dkct_tr_get_kw8(31), psrc->fipo);
  }
  /* char 8 end */
  if((psrc->dkcto).win) {
    fputs(dkct_tr_get_kw8(23), psrc->fipo);
  }
  fputs(dkct_tr_get_kw8(25), psrc->fipo);
}



/**	Write debug output to show the matching rule.
	@param	psrc	Source structure.
	@param	stm	State machine.
	@param	rp	Rule to show.
*/
static
void
dkct_au_debug_matching_rule(
  DKCT_SRC *psrc, DKCT_STM *stm, DKCT_STM_RULE *rp
)
{
  char const	*fnptr;	/* Debug output file. */
  char const	*p1;	/* Current state. */
  char const	*p2;	/* Input. */
  char const	*p3;	/* Next state. */
  char const	*p4;	/* Output. */

  if((psrc->dkcto).deb) {
    p1 = p2 = p3 = p4 = dkct_au_kw8[0];
    if(rp) {
      if(rp->state) { p1 = (rp->state)->name; }
      if(rp->input) { p2 = (rp->input)->name; }
      if(rp->newstate) { p3 = (rp->newstate)->name; }
      if(rp->output) { p4 = (rp->output)->name; }
    } else {
      if(stm->ds) { p3 = (stm->ds)->name; }
      if(stm->dout) { p4 = (stm->dout)->name; }
    }
    fnptr = dkct_tr_get_kw8(((psrc->dkcto).deb == 2) ? 28 : 29);
    psrc->lineno = stm->lineno;
    if(rp) { psrc->lineno = rp->lineno; }
    fputs(dkct_tr_get_kw8(67), psrc->fipo);
    if((psrc->dkcto).win) {
      fputs(dkct_tr_get_kw8(21), psrc->fipo);
      /* char 16 start */
      if((psrc->dkcto).deb == 1) {
        fputs(dkct_tr_get_kw8(30), psrc->fipo);
      }
      fputs(dkct_tr_get_kw8(61), psrc->fipo);
      dkct_tr_show_filename_and_lineno(psrc);
      fputs(dkct_tr_get_kw8(35), psrc->fipo);
      fputs(fnptr, psrc->fipo);
      fputs(dkct_tr_get_kw8(34), psrc->fipo);
      fputs(dkct_tr_get_kw8(61), psrc->fipo);
      fputs(dkct_au_kw8[73], psrc->fipo);
      fputs(dkct_au_kw8[2], psrc->fipo);
      fputs(p1, psrc->fipo);
      fputs(dkct_au_kw8[2], psrc->fipo);
      fputs(p2, psrc->fipo);
      fputs(dkct_au_kw8[2], psrc->fipo);
      fputs(p3, psrc->fipo);
      fputs(dkct_au_kw8[2], psrc->fipo);
      fputs(p4, psrc->fipo);
      fputs(dkct_au_kw8[74], psrc->fipo);
      fputs(dkct_tr_get_kw8(35), psrc->fipo);
      fputs(fnptr, psrc->fipo);
      fputs(dkct_tr_get_kw8(34), psrc->fipo);
      fputs(dkct_tr_get_kw8(37), psrc->fipo);
      fputs(fnptr, psrc->fipo);
      fputs(dkct_tr_get_kw8(34), psrc->fipo);
      if((psrc->dkcto).deb == 1) {
        fputs(dkct_tr_get_kw8(31), psrc->fipo);
      }
      /* char 16 end */
      fputs(dkct_tr_get_kw8(22), psrc->fipo);
    }
    /* char 8 start */
    if((psrc->dkcto).deb == 1) {
      fputs(dkct_tr_get_kw8(30), psrc->fipo);
    }
    fputs(dkct_tr_get_kw8(33), psrc->fipo);
    dkct_tr_show_filename_and_lineno(psrc);
    fputs(dkct_tr_get_kw8(35), psrc->fipo);
    fputs(fnptr, psrc->fipo);
    fputs(dkct_tr_get_kw8(34), psrc->fipo);
    
    fputs(dkct_tr_get_kw8(33), psrc->fipo);
    fputs(dkct_au_kw8[73], psrc->fipo);
    fputs(dkct_au_kw8[2], psrc->fipo);
    fputs(p1, psrc->fipo);
    fputs(dkct_au_kw8[2], psrc->fipo);
    fputs(p2, psrc->fipo);
    fputs(dkct_au_kw8[2], psrc->fipo);
    fputs(p3, psrc->fipo);
    fputs(dkct_au_kw8[2], psrc->fipo);
    fputs(p4, psrc->fipo);
    fputs(dkct_au_kw8[74], psrc->fipo);
    fputs(dkct_tr_get_kw8(35), psrc->fipo);
    fputs(fnptr, psrc->fipo);
    fputs(dkct_tr_get_kw8(34), psrc->fipo);
    
    fputs(dkct_tr_get_kw8(37), psrc->fipo);
    fputs(fnptr, psrc->fipo);
    fputs(dkct_tr_get_kw8(34), psrc->fipo);
    if((psrc->dkcto).deb == 1) {
      fputs(dkct_tr_get_kw8(31), psrc->fipo);
    }

    /* char 8 end */
    if((psrc->dkcto).win) {
      fputs(dkct_tr_get_kw8(23), psrc->fipo);
    }
    fputs(dkct_tr_get_kw8(25), psrc->fipo);
  }
}



void
dkct_au_write_functions(DKCT_SRC *psrc, DKCT_STM *stm, int f_static)
{
  DKCT_STM_ENTRY	*prevstate;	/* Current state. */
  DKCT_STM_RULE		*rp;		/* Rule to process. */
  unsigned long		 nwildcards;	/* Number of wildcards. */
  unsigned long		 i;		/* Current wildcard block to finish. */
  /*
  	Reset function.
  */
  if(f_static) {
    fputs(dkct_au_kw8[23], psrc->fipo);
    dkct_au_write_stm_name(psrc, stm);
    fputs(dkct_au_kw8[24], psrc->fipo);
    fputs(dkct_au_kw8[25], psrc->fipo);
    fputs(dkct_au_kw8[32], psrc->fipo);
  }
  fputs(dkct_au_kw8[33], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[34], psrc->fipo);
  if(stm->rs) {
    fputs((stm->rs)->name, psrc->fipo);
  } else {
    fputs(dkct_au_kw8[36], psrc->fipo);
  }
  fputs(dkct_au_kw8[35], psrc->fipo);
  /*
  	Transition function.
  */
  if(f_static) {
    fputs(dkct_au_kw8[28], psrc->fipo);
    dkct_au_write_stm_name(psrc, stm);
    fputs(dkct_au_kw8[29], psrc->fipo);
    fputs(dkct_au_kw8[30], psrc->fipo);
    fputs(dkct_au_kw8[32], psrc->fipo);
  }
  fputs(dkct_au_kw8[37], psrc->fipo);
  dkct_au_write_stm_name(psrc, stm);
  fputs(dkct_au_kw8[38], psrc->fipo);
  if(stm->dout) {
    fputs((stm->dout)->name, psrc->fipo);
  } else {
    fputs(dkct_au_kw8[36], psrc->fipo);
  }
  fputs(dkct_au_kw8[39], psrc->fipo);
  if((psrc->dkcto).deb) {
    /* Debug messages for entering function */
    dkct_au_debug_transition(psrc, stm, 0);
  }
  fputs(dkct_au_kw8[40], psrc->fipo);
  if(stm->ds) {
    fputs((stm->ds)->name, psrc->fipo);
  } else {
    fputs(dkct_au_kw8[36], psrc->fipo);
  }
  fputs(dkct_au_kw8[39], psrc->fipo);
  fputs(dkct_au_kw8[46], psrc->fipo);
  /*
  	Exact rules
  */
  prevstate = NULL;
  dk3sto_it_reset(stm->i_exact);
  while((rp = (DKCT_STM_RULE *)dk3sto_it_next(stm->i_exact)) != NULL) {
    if(prevstate) {
      if(dk3str_c8_cmp(prevstate->name, (rp->state)->name)) {
        fputs(dkct_au_kw8[52], psrc->fipo);
        fputs(dkct_au_kw8[50], psrc->fipo);
        fputs(dkct_au_kw8[48], psrc->fipo);
        fputs((rp->state)->name, psrc->fipo);
        fputs(dkct_au_kw8[49], psrc->fipo);
	fputs(dkct_au_kw8[51], psrc->fipo);
      } else {
      }
    } else {
      fputs(dkct_au_kw8[47], psrc->fipo);
      fputs(dkct_au_kw8[48], psrc->fipo);
      fputs((rp->state)->name, psrc->fipo);
      fputs(dkct_au_kw8[49], psrc->fipo);
      fputs(dkct_au_kw8[51], psrc->fipo);
    }
    prevstate = rp->state;
    fputs(dkct_au_kw8[53], psrc->fipo);
    fputs((rp->input)->name, psrc->fipo);
    fputs(dkct_au_kw8[54], psrc->fipo);
    dkct_au_debug_matching_rule(psrc, stm, rp);
    dkct_au_write_transition_result(psrc, stm, rp, 12);
    fputs(dkct_au_kw8[55], psrc->fipo);
  }
  if(prevstate) {
    fputs(dkct_au_kw8[52], psrc->fipo);
    fputs(dkct_au_kw8[50], psrc->fipo);
    fputs(dkct_au_kw8[45], psrc->fipo);
  }
  fputs(dkct_au_kw8[44], psrc->fipo);
  /*
  	Wildcard rules
  */
  nwildcards = 0UL;
  dk3sto_it_reset(stm->i_wildcard);
  while((rp = (DKCT_STM_RULE *)dk3sto_it_next(stm->i_wildcard)) != NULL) {
    fputs(dkct_au_kw8[60], psrc->fipo);
    if(rp->state) {
      fputs(dkct_au_kw8[64], psrc->fipo);
      fputs((rp->state)->name, psrc->fipo);
    } else {
      if(rp->input) {
        fputs(dkct_au_kw8[65], psrc->fipo);
	fputs((rp->input)->name, psrc->fipo);
      } else {
        fputs(dkct_au_kw8[36], psrc->fipo);
      }
    }
    fputs(dkct_au_kw8[61], psrc->fipo);
    dkct_au_debug_matching_rule(psrc, stm, rp);
    dkct_au_write_transition_result(psrc, stm, rp, 6);
    fputs(dkct_au_kw8[62], psrc->fipo);
    nwildcards++;
  }
  dkct_au_debug_matching_rule(psrc, stm, NULL);
  for(i = 0; i < nwildcards; i++) {
    fputs(dkct_au_kw8[63], psrc->fipo);
  }
  fputs(dkct_au_kw8[45], psrc->fipo);
  fputs(dkct_au_kw8[77], psrc->fipo);
  fputs(dkct_au_kw8[42], psrc->fipo);
  /* DEBUG: Invalid st pointer */
  fputs(dkct_au_kw8[43], psrc->fipo);
  if((psrc->dkcto).deb) {
    /* Debug messages for entering function */
    dkct_au_debug_transition(psrc, stm, 1);
  }
  fputs(dkct_au_kw8[76], psrc->fipo);
  fputs(dkct_au_kw8[41], psrc->fipo);
}



/* vim: set ai sw=2 : */

