#!/usr/bin/perl
#
#-----------------------------------------------------------------
#
# Name:	mkesm.pl
#
# RCS:  $Id: mkesm.pl,v 1.4 2002/01/02 00:50:42 bob Exp $
#
# Copyright (C) 2001, Agile Storage, Inc.
#
# Description:	Eagle State Machine generation tool
#
# Created by:	Bob Fozard
#
# Date Created:	3/20/01
#
#-----------------------------------------------------------------
#

use Text::ParseWords;
use File::Basename;

$tl_name = "mkesm.pl";
%state_hash = ();
%event_hash = ();
%fns_hash = ();
%func_hash = ();
$fns_idx = 0;
$numActions = 0;
$numStates = 0;
$yield = 0;
$stack_size = 0;

$action_args = "(esm_handle_t	handle,
						int32		nextState,
						esm_event_t thisEvent,
						void		* userInfo)";

sub print_func_hdr;
sub dump_file_start;
sub dump_funcs;
sub dump_fns;
sub dump_event_vect;
sub dump_gptr;
sub dump_xlate;
sub dump_create_func;
sub dump_destroy_func;
sub dump_create_action;
sub dump_table;
sub dump_nop_func;
sub dump_include_file;
sub emit_edge;
sub process_prefix;
sub process_queue;
sub process_yield;
sub process_stack_size;
sub process_create_action;
sub process_exclude;
sub process_include;
sub process_table;
sub process_row;

if ($#ARGV < 0 || $#ARGV > 2)
{
    print "usage: mkesm.pl [-d output_dir] <filename.sm>\n";
    exit -1;
}

$output_dir = "";
$smfilename = "";

while ($#ARGV >= 0) {
    $cmd_arg = shift;
    if ($cmd_arg eq "-d") {
        $output_dir = shift;
    } elsif ($smfilename) {
        die "usage: mkesm.pl [-d output_dir] <filename.sm>\n";
    } else {
        $smfilename = $cmd_arg;
    }
}
$output_dir = dirname ($smfilename) if ($output_dir eq "");

print "Opening sm file: $smfilename\n";
open SMFILE, "<$smfilename" or 
    die "Couldn't open/read sm file: $smfilename\n";

$line = 1;
$keep = "";

PROC_LINES:
while (<SMFILE>)
{
	# provide \ as a line continuation char.
	if (/\\/) 
	{
		chop; chop;
		$keep = $keep . $_;
		next PROC_LINES;
	} 

	$_ = $keep . $_;
	$keep = "";
	@words = split;

    # skip empty lines.
    if (! @words) {next PROC_LINES;}
    
    # skip # comment lines.
    $_ = shift @words;
	if (/^\#/) {next PROC_LINES;}

	# sub-process line based on token.
	if (/^STATE_MACHINE_NAME$/) {process_prefix (@words); next PROC_LINES;}

	if (/^MAX_QUEUE_ENTRIES$/) {process_queue (@words); next PROC_LINES;}

    if (/^CAN_YIELD$/) {process_yield (@words); next PROC_LINES;}

    if (/^STACK_SIZE$/) {process_stack_size (@words); next PROC_LINES;}

	if (/^CREATE_ACTION$/) {process_create_action (@words); next PROC_LINES;}

	if (/^exclude$/) {process_exclude (@words); next PROC_LINES;}

	if (/^include$/) {process_include (@words); next PROC_LINES;}

	if (/^STATE_TABLE_DEF$/) {process_table (@words); next PROC_LINES;}

	if (defined $table_cols and (@words >= $table_cols))
	{
		unshift @words, $_;
		process_row (@words);
		next PROC_LINES;
	}

	print "$tl_name: ERROR: file $smfilename, line $line: syntax error\n";
	$dont_gen = 1;
}
continue
{
    ++ $line;
}

if (! defined $prefix)
{
	print "$tl_name: ERROR: file $smfilename: missing STATE_MACHINE_NAME statement\n";
	$dont_gen = 1;
}

if (! defined $queue)
{
	print "$tl_name: ERROR: file $smfilename: missing MAX_QUEUE_ENTRIES statement\n";
	$dont_gen = 1;
}

if (! defined $create_action)
{
	print "$tl_name: ERROR: file $smfilename: missing CREATE_ACTION statement\n";
	$dont_gen = 1;
}

if (! defined $state_hash{$create_next_state})
{
	print "$tl_name: ERROR: file $smfilename, CREATE_ACTION <nextState> $create_next_state is not a listed state\n";
	$dont_gen = 1;
}

if (defined $dont_gen) {exit -1;}

$codefilename = $output_dir .
    "/" . basename ($smfilename, ".sm") . ".c";
print "Opening code file: $codefilename\n";
open CODEFILE, ">$codefilename" or 
    die "Couldn't open/write code file: $codefilename\n";

$includefilename = $output_dir .
    "/" . basename ($smfilename, ".sm") . ".h";
print "Opening include file: $includefilename\n";
open INCLUDEFILE, ">$includefilename" or 
    die "Couldn't open/write include file: $includefilename\n";

dump_file_start ();

dump_fns ();

dump_actions ();

dump_event_vect (@event_list);

dump_gptr ();

$state_count = @state_list;
unshift @state_list, "state";
dump_xlate (@state_list);
shift @state_list;

$event_count = @event_list;
unshift @event_list, "event";
dump_xlate (@event_list);
shift @event_list;

dump_create_action ();

dump_table ();

dump_create_func ();

dump_destroy_func ();

dump_nop_func ();

if ($need_endif)
  {
	for (my $i = 0; $i < $need_endif; ++$i)
	  {
		print CODEFILE "#endif\n";
	  }
  }

dump_include_file ();

exit 0;

sub
process_create_action
{
	if (defined $create_action)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate create_action statement\n";
		$dont_gen = 1;
	}

	if (1 != @_)
	{ 
		$create_action = shift;

		$_ = shift;
		if (/^\#/) {return;}

	    print "$tl_name: ERROR: file $smfilename, line $line: CREATE_ACTION <action>/<newState>\n";
		$dont_gen = 1;
	}
	$create_action = shift;

	$_ = $create_action;

	if (! /\//)
	{
	    print "$tl_name: ERROR: file $smfilename, line $line: CREATE_ACTION format is: <funcion>/<nextState>\n";
		$dont_gen = 1;
	}

	@fns = split /\//;
	if (2 != @fns)
	{
	    print "$tl_name: ERROR: file $smfilename, line $line: CREATE_ACTION format is: <funcion>/<nextState>\n";
		$dont_gen = 1;
	}

	my $func = shift @fns;

	if ("" eq $func)
	{
	    print "$tl_name: ERROR: file $smfilename, line $line: CREATE_ACTION format is: <funcion>/<nextState>\n";
		$dont_gen = 1;
	}

	$_ = $func;
	if (/\W/)
	{
		print "$tl_name: ERROR: file $smfilename, line $line: <function> contains illegal chars\n";
		$dont_gen = 1;
	}

	$create_action = $func;

	$create_next_state = shift @fns;
}

sub
process_queue
{
	if (defined $queue)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate MAX_QUEUE_ENTRIES statement\n";
		$dont_gen = 1;
	}

	if (1 != @_)
	{ 
		$queue = shift;

		$_ = shift;
		if (/^\#/) {return;}

	    print "$tl_name: ERROR: file $smfilename, line $line: MAX_QUEUE_ENTRIES <depth>\n";
		$dont_gen = 1;
	}
	$queue = shift;
}

sub
process_yield
{
	if ($yield > 0)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate CAN_YIELD statement\n";
		$dont_gen = 1;
	}

	$yield = 1;
}

sub
process_stack_size
{
	if ($stack_size > 0)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate STACK_SIZE statement\n";
		$dont_gen = 1;
	}

	if (1 != @_)
	{ 
		$stack_size = shift;

		$_ = shift;
		if (/^\#/) {return;}

	    print "$tl_name: ERROR: file $smfilename, line $line: STACK_SIZE <size>\n";
		$dont_gen = 1;
	}
	$stack_size = shift;
}


sub
process_prefix
{
	if (defined $prefix)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate STATE_MACHINE_NAME statement\n";
		$dont_gen = 1;
	}

	if (1 != @_)
	{ 
		$prefix = shift;

		$_ = shift;
		if (/^\#/) {return;}

	    print "$tl_name: ERROR: file $smfilename, line $line: STATE_MACHINE_NAME <name>\n";
		$dont_gen = 1;
	}
	$prefix = shift;
}

sub
process_table
{
	if (defined $table_cols)
	{
		print "$tl_name: ERROR: file $smfilename, line $line: STATE_TABLE_DEF can be used once per file\n";
		$dont_gen = 1;
	}

	if (! @_)
	{ 
	    print "$tl_name: ERROR: file $smfilename, line $line: STATE_TABLE_DEF <state1> ... <staten>\n";
		$dont_gen = 1;
	}


	# build hash table of all states.
	my $idx = 0;
	my @list = @_;
	while (@list)
    {
		$_ = shift @list;
		if (/^\#/) {return;}
		$state_hash{$_} = $idx++;
		$table_cols++;
		push @state_list, $_;
	}

	if ($yield > 0)
	{
		if ($idx > 1)
		{
			print "$tl_name: ERROR: file $smfilename, line $line: only 1 state permitted if CAN_YIELD defined\n";
			$dont_gen = 1;
		}
	}
}

sub
process_row
{
	my @list = @_;
    $event = shift @list;

	if (defined $event_hash{$event})
	{
	    print "$tl_name: ERROR: file $smfilename, line $line: event name $event duplicated";
		print " (see line $event_hash{$event})\n";
		$dont_gen = 1;
		return;
	}
	$event_hash{$event} = $line;

	push @event_list, $event;
	my @fns_vect;

    EDGE_LOOP:
	while (@list)
	{
		my $edge = shift @list;
		
		if ("na" eq $edge)
		{
			push @fns_vect, "na";
			next EDGE_LOOP;
		}

		$_ = $edge;

		if (/^\#/) {@list = undef; last EDGE_LOOP;}

		if (! /\//)
		{
		    print "$tl_name: ERROR: file $smfilename, line $line: edge format is: <func-suffix>/<next-state>\n";
			$dont_gen = 1;
			next EDGE_LOOP;
		}

		@fns = split /\//;
		if (2 != @fns)
		{
		    print "$tl_name: ERROR: file $smfilename, line $line: edge format is: <func-suffix>/<next-state>\n";
			$dont_gen = 1;
			next EDGE_LOOP;
		}

		my $func = shift @fns;

		if ("" eq $func)
		{
		    print "$tl_name: ERROR: file $smfilename, line $line: edge format is: <func-suffix>/<next-state>\n";
			$dont_gen = 1;
			next EDGE_LOOP;
		}

		$_ = $func;
		if (/\W/)
		{
			print "$tl_name: ERROR: file $smfilename, line $line: <func-suffix> contains illegal chars\n";
			$dont_gen = 1;
			next EDGE_LOOP;
		}
		
		my $next_state = shift @fns;
		if (! defined $state_hash{$next_state})
		{
			print "$tl_name: ERROR: file $smfilename, line $line: <next-state> $next_state is not a listed state\n";
			$dont_gen = 1;
			next EDGE_LOOP;
		}
		# if the function isn't already known, add it.
		if (! defined $func_hash{$func})
		{
			if ($yield > 0)
			{
				if ($numActions > 0)
				{
					print "$tl_name: ERROR: file $smfilename, line $line: only one action function allowed if CAN_YIELD defined\n";
					$dont_gen = 1;
					next EDGE_LOOP;
				}
			}
			$func_hash{$func} = $func;
            $numActions++;
		}

		# if the function/next-state pair doesn't already exist, add it.
        my $ns_idx = $state_hash{$next_state};
		if (! defined $fns_hash{($func . "-" . $ns_idx)})
		{
			$fns_hash{($func . "-" . $ns_idx)} = $fns_idx++;
		}

		push @fns_vect, $fns_hash{($func . "-" . $ns_idx)};
	}

	if (@fns_vect != @state_list)
	{
	    print "$tl_name: ERROR: file $smfilename, line $line: too few/many entries compared with state count\n";
		$dont_gen = 1;
	}

	push @evt_fns_vects, [@fns_vect];
}

sub
process_exclude
{
	my @list = @_;

	if (defined @excludes)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate exclude statement\n";
		$dont_gen = 1;
	}

	while (@list)
	{
		$_ = shift @list;
		if (/^\#/) {return;}
		push @excludes, $_;
    }
}

sub
process_include
{
	my @list = @_;

	if (defined @includes)
	{
		print "$tl_name: ERROR: file $smfilename: line $line: duplicate include statement\n";
		$dont_gen = 1;
	}

	while (@list)
	{
		$_ = shift @list;
		if (/^\#/) {return;}
		push @includes, $_;
    }
}

# dump a decl for each function found.
sub
dump_funcs
{
	my @list = keys %func_hash;

	print INCLUDEFILE "int32 $prefix";
	print INCLUDEFILE "_bad_state $action_args;\n";

	while (@list)
	{
		my $func = shift @list;
		print INCLUDEFILE "int32 $prefix";
		print INCLUDEFILE "_$func $action_args;\n";
	}
	print INCLUDEFILE "\n";
}

sub
dump_fns
{
	my $nstate = "$prefix" . "_STATE_$state_list[0]";
	printf CODEFILE "esm_actionFunc_t $prefix";
	printf CODEFILE "_func_bad = {$prefix";
	$nstate =~ tr/a-z/A-Z/;
#	printf CODEFILE "_bad_state, 0};\n";
	printf CODEFILE "_bad_state, $nstate};\n";

	while ((my $fns, my $idx) = each %fns_hash)
	{
		@fns = split /-/, $fns;

		my $func = shift @fns;
		my $ns_idx = shift @fns;
		$nstate = "$prefix" . "_STATE_$state_list[$ns_idx]";
		$nstate =~ tr/a-z/A-Z/;

		printf CODEFILE "esm_actionFunc_t $prefix";
		printf CODEFILE "_func$idx = {$prefix";
#		printf CODEFILE "_$func, $ns_idx};\n";
		printf CODEFILE "_$func, $nstate};\n";
	}
	printf CODEFILE "\n";
}

sub
emit_edge
{
	my $arg = shift @_;

	if ("na" eq $arg)
	{
		print CODEFILE "& $prefix";
		print CODEFILE "_func_bad";
	}
	else
	{
		print CODEFILE "& $prefix";
		print CODEFILE "_func$arg";
	}
}

sub
dump_actions
{
	my $idx = 0;
	my $state_count = @state_list;

	while (@evt_fns_vects)
	{
		print CODEFILE "esm_actionFunc_t  *$prefix";
		print CODEFILE "_event_$idx\[$state_count\] = {";

		my $fns_arr = shift @evt_fns_vects;
		my @fns_vect = @$fns_arr;

		while (1 < @fns_vect)
		{
			my $edge = shift @fns_vect;

			emit_edge ($edge);
			print CODEFILE ", ";
		}

		emit_edge (shift @fns_vect);
		print CODEFILE "};\n";
		++ $idx;
	}
	print CODEFILE "\n\n";
}

sub
dump_event_vect
{
	my @list = @_;
	my $count = @_;
	print CODEFILE "esm_actionFunc_t **$prefix";
	print CODEFILE "_v[$count] = {\n";

	for (my $i = 0; $i < $count-1; ++$i)
	{
	    print CODEFILE "\t\t\t\t\t\t\t\t$prefix";
		print CODEFILE "_event_$i,\n";
	}

	--$count;
	print CODEFILE "\t\t\t\t\t\t\t\t$prefix";
	print CODEFILE "_event_$count};\n\n";
}

sub
dump_gptr
{
	print CODEFILE "esm_actionFunc_t ***$prefix = & $prefix";
	print CODEFILE "_v[0];\n\n";
	print CODEFILE "int32 $prefix";
	print CODEFILE "_trace_flag = 0;\n\n";
}

sub
dump_xlate
{
    my @list = @_;
    my $xtype = shift @list;
    my $count = @list;

    print CODEFILE "char *$prefix"; 
    print CODEFILE "_xlate_";
    print CODEFILE "$xtype";
    print CODEFILE "[$count] = {";
    
    while (1 < @list)
    {
	 my $state = shift @list;
	print CODEFILE "\"$state\", ";
    }
    
    my $state = shift @list;
    print CODEFILE "\"$state\"};\n";

	print CODEFILE "\n";
}

sub
dump_file_start
{
  $need_endif = 0;

	print CODEFILE "/*
 *-----------------------------------------------------------------
 *
 * Name:	$prefix.c
 *
 * RCS:  $Id: mkesm.pl,v 1.4 2002/01/02 00:50:42 bob Exp $
 *
 * Copyright (C) 2001, Agile Storage, Inc.
 *
 * Description:	This file is automatically created by the Eagle State
 *				Machine generation tool, $tl_name.
 *
 *				DO NOT MAKE ANY MANUAL CHANGES TO THIS FILE.
 *
 * Created by:	automatically
 *
 * Date Created:	
 *
 *-----------------------------------------------------------------
 */

";
	print INCLUDEFILE "/*
 *-----------------------------------------------------------------
 *
 * Name:	$prefix.h
 *
 * RCS:  $Id: mkesm.pl,v 1.4 2002/01/02 00:50:42 bob Exp $
 *
 * Copyright (C) 2001, Agile Storage, Inc.
 *
 * Description:	This file is automatically created by the Eagle State
 *				Machine generation tool, $tl_name.
 *
 *				DO NOT MAKE ANY MANUAL CHANGES TO THIS FILE.
 *
 * Created by:	automatically
 *
 * Date Created:	
 *
 *-----------------------------------------------------------------
 */

";
	$include_ifdef = $prefix;
	$include_ifdef =~ tr/a-z/A-Z/;
	$include_ifdef = "_".$include_ifdef."_H";
	s/./_/ for $include_ifdef;
   print INCLUDEFILE "#ifndef $include_ifdef\n#define $include_ifdef\n\n";

  print CODEFILE << 'EOF';
EOF

  if (defined @excludes)
  {
	++ $need_endif;
	print CODEFILE "#if ! (";

	while (@excludes)
	{
	  my $bad_def = shift @excludes;

	  print CODEFILE "defined($bad_def)";

	  if (@excludes)
		{
		  print CODEFILE " || ";
		}
	}
	print CODEFILE ")\n";
  }

  if (defined @includes)
  {
	++ $need_endif;
	print CODEFILE "#if (";

	while (@includes)
	{
	  my $bad_def = shift @includes;

	  print CODEFILE "defined($bad_def)";

	  if (@excludes)
		{
		  print CODEFILE " && ";
		}
	}
	print CODEFILE ")\n";
  }

  print CODEFILE << 'EOF';
#include "nfx-incl.h"
#include "../sm-esm/esm-api.h"
EOF

  my $inc_name = basename ($includefilename);

  print CODEFILE "#include \"$inc_name\"\n\n";
}

sub
dump_create_action
{
	my $ns_idx = $state_hash{$create_next_state};
	my $nstate = "$prefix" . "_STATE_$state_list[$ns_idx]";
	$nstate =~ tr/a-z/A-Z/;

	printf CODEFILE "esm_actionFunc_t $prefix";
	printf CODEFILE "_create_action = {$prefix";
#	printf CODEFILE "_$create_action, $ns_idx};\n";
	printf CODEFILE "_$create_action, $nstate};\n";

	print INCLUDEFILE "int32 $prefix";
	print INCLUDEFILE "_$create_action $action_args;\n";
}

sub
dump_table
{
	print CODEFILE "
/*------------------------------------------------------------------
 *
 *	State Machine Table
 *
 *-----------------------------------------------------------------*/
";
	print CODEFILE "esm_table_t $prefix";
	print CODEFILE "_sm_table = { & $prefix";
	print CODEFILE "_v[0],\n\t\t\t\t\t\t\t\t$prefix";
	print CODEFILE "_xlate_state,\n\t\t\t\t\t\t\t\t$prefix";
	print CODEFILE "_xlate_event,\n\t\t\t\t\t\t\t\t$event_count, $state_count, $queue, $yield, $stack_size, \"$prefix\" };\n";
}

sub
print_func_hdr
{
	my @list = @_;
    $func_name = shift @list;

	$hdr = "
/*-----------------------------------------------------------------
 * Name:	$func_name()
 *
 * Description:
 *
 * Created by:	automatic
 *
 * Date Created:
 *
 *-----------------------------------------------------------------
 */
";
	print CODEFILE "$hdr";
}

sub
dump_create_func
{
  print_func_hdr($prefix._sm_create);
  print CODEFILE "int32\n";
  print CODEFILE "$prefix";
  print CODEFILE "_sm_create (\n\tesm_handle_t\t*handle,\n\tvoid\t\t\t*cb_ptr,\n";
  print CODEFILE "\tvoid\t\t\t(*trashFunc)(\n\t\t\tesm_handle_t\thandle,\n";
  print CODEFILE "\t\t\tesm_event_t\t\tevent,\n";
  print CODEFILE "\t\t\tvoid\t\t\t*userInfo)\n)\n";
  print CODEFILE "{\n\treturn esm_instantiate (& $prefix";
  print CODEFILE "_sm_table,\n\t\t\t\t\t\t\t& $prefix";
  print CODEFILE "_create_action,\n\t\t\t\t\t\t\thandle,\n\t\t\t\t\t\t\tcb_ptr,\n";
  print CODEFILE "\t\t\t\t\t\t\ttrashFunc);\n}\n\n";
}

sub
dump_destroy_func
{
  print_func_hdr($prefix._sm_destroy);
  print CODEFILE "$func_hdr";
  print CODEFILE "int32\n";
  print CODEFILE "$prefix";
  print CODEFILE "_sm_destroy (\n\tesm_handle_t\thandle\n)\n";
  print CODEFILE "{\n\treturn esm_destroy (handle);\n}\n";
}

sub
dump_nop_func
{
  print_func_hdr($prefix._nop);
  print CODEFILE "$func_hdr";
  print CODEFILE "int32\n";
  print CODEFILE "$prefix";
  print CODEFILE "_nop (\n";
  print CODEFILE "\tesm_handle_t\thandle unused__,\n";
  print CODEFILE "\tint32\t\t\tnextState,\n";
  print CODEFILE "\tesm_event_t\t\tthisEvent unused__,\n";
  print CODEFILE "\tvoid*\t\t\tuserInfo unused__)\n";
  print CODEFILE "{\n\treturn nextState;\n}\n\n";
}

# print user decls for user-defined fns.
# print a define for each state, and for each event. Also prototype
# each function.
sub 
dump_include_file
{
  # dump function decs
  dump_funcs ();
  
  # dump state defs.
  my @list = @state_list;
  my $value = 0;
  my $max_label = 0;
  
  while (@list)
    {
      my $state = shift @list;
      my $label = "$prefix" . "_STATE_$state";

      $label =~ tr/a-z/A-Z/;

      print INCLUDEFILE "#define $label\t\t$value\n";
      ++$value;
    }
  
  # dump event defs.
  @list = @event_list;
  $value = 0;
  
  while (@list)
    {
      my $state = shift @list;
      my $label = "$prefix" . "_EVENT_$state";

      $label =~ tr/a-z/A-Z/;

      print INCLUDEFILE "#define $label\t\t$value\n";
      ++$value;
    }
  $max_label = "$prefix" . "_EVENT_MAXIMUM";
  $max_label =~ tr/a-z/A-Z/;
  print INCLUDEFILE "#define $max_label\t\t$value\n";

  print INCLUDEFILE "\n";

  # dump create func proto.
  print INCLUDEFILE "int32 ";
  print INCLUDEFILE "$prefix";
  print INCLUDEFILE "_sm_create (\n";
  print INCLUDEFILE "\tesm_handle_t\t*handle,\n";
  print INCLUDEFILE "\tvoid\t\t\t*cb_ptr,\n";
  print INCLUDEFILE "\tvoid\t\t\t(*trashFunc)(\n\t\t\tesm_handle_t\thandle,\n";
  print INCLUDEFILE "\t\t\tesm_event_t\t\tevent,\n";
  print INCLUDEFILE "\t\t\tvoid\t\t\t*userInfo));\n\n";

  # dump destroy func proto.
  print INCLUDEFILE "int32 ";
  print INCLUDEFILE "$prefix";
  print INCLUDEFILE "_sm_destroy (esm_handle_t handle);\n\n";

  # dump nop func proto.
  print INCLUDEFILE "int32 ";
  print INCLUDEFILE "$prefix";
  print INCLUDEFILE "_nop (\n";
  print INCLUDEFILE "\tesm_handle_t\thandle,\n";
  print INCLUDEFILE "\tint32\t\t\tnextState,\n";
  print INCLUDEFILE "\tesm_event_t\t\tthisEvent,\n";
  print INCLUDEFILE "\tvoid*\t\t\tuserInfo);\n";

  print INCLUDEFILE "\n";
  print INCLUDEFILE "#endif	/* $include_ifdef */\n\n";
}
