From 0506ec019bfbcd55c452719cb38107d8cfb4af73 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Thu, 30 Sep 2010 15:17:54 -0700 Subject: [PATCH] create hsmc repo --- .hgignore | 1 + TODO | 24 + bin/flex.exe | Bin 0 -> 148992 bytes bin/yacc.exe | Bin 0 -> 96768 bytes example/parsetest/parsetest.hsm | 97 ++ example/traffic/main.cpp | 72 ++ example/traffic/traffic.hsm | 47 + hsmc.sln | 32 + hsmc.vcproj | 151 +++ hsmc.vpj | 98 ++ hsmc.vpw | 6 + source/Makefile | 77 ++ source/autofile.h | 36 + source/config.h | 127 +++ source/getopt.cpp | 138 +++ source/getopt.h | 20 + source/hsm-lexer.c | 1684 +++++++++++++++++++++++++++++++ source/hsm-parser.tab.c | 469 +++++++++ source/hsm-parser.tab.h | 17 + source/hsm.l | 86 ++ source/hsm.y | 135 +++ source/hsmc.dev | 159 +++ source/machine.h | 488 +++++++++ source/main.cpp | 1387 +++++++++++++++++++++++++ source/main.h | 29 + source/state.h | 33 + 26 files changed, 5413 insertions(+) create mode 100644 .hgignore create mode 100644 TODO create mode 100644 bin/flex.exe create mode 100644 bin/yacc.exe create mode 100644 example/parsetest/parsetest.hsm create mode 100644 example/traffic/main.cpp create mode 100644 example/traffic/traffic.hsm create mode 100644 hsmc.sln create mode 100644 hsmc.vcproj create mode 100644 hsmc.vpj create mode 100644 hsmc.vpw create mode 100644 source/Makefile create mode 100644 source/autofile.h create mode 100644 source/config.h create mode 100644 source/getopt.cpp create mode 100644 source/getopt.h create mode 100644 source/hsm-lexer.c create mode 100644 source/hsm-parser.tab.c create mode 100644 source/hsm-parser.tab.h create mode 100644 source/hsm.l create mode 100644 source/hsm.y create mode 100644 source/hsmc.dev create mode 100644 source/machine.h create mode 100644 source/main.cpp create mode 100644 source/main.h create mode 100644 source/state.h diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..02774c5 --- /dev/null +++ b/.hgignore @@ -0,0 +1 @@ +.svn\/ diff --git a/TODO b/TODO new file mode 100644 index 0000000..8e04dc2 --- /dev/null +++ b/TODO @@ -0,0 +1,24 @@ + + +TODO List - by Priority +======================= + + +* make sure Update not called from unsafe section (inside machine) + +* add transition guards + adds some complication (not much?) + can you then have multiple transitions per event? I say NO. + needed? + +* Add history? Shallow? Deep? + +* add C-style comment support? + +* change to using text templates for text output??? + +* document language + +* document behavior (such as Transition always causing an exit+entry sequence) + + diff --git a/bin/flex.exe b/bin/flex.exe new file mode 100644 index 0000000000000000000000000000000000000000..b378ad2952209011b8f0663db30c40a9ca79b4d2 GIT binary patch literal 148992 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 z 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 MywN0b|Nr{?cVFMsdH?_b literal 0 HcmV?d00001 diff --git a/bin/yacc.exe b/bin/yacc.exe new file mode 100644 index 0000000000000000000000000000000000000000..a4d68b5527c3e559798c872b8abd195806e6c11b GIT binary patch literal 96768 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 +#include + +#include // for Sleep() +#include // for kbhit() + + +class MyStoplight: public stoplight +{ +public: + virtual void DoPOST() + { + printf("DoPOST\n"); + } + virtual void CheckForError() + { + if ( kbhit() ) + { + printf("Encountered critical error\n"); + HSMTrigger(FAILURE); + } + } + virtual void GreenOff () + { + printf("Green Off\n"); + } + virtual void GreenOn() + { + printf("Green On\n"); + } + virtual void YellowOff() + { + printf("Yellow Off\n"); + } + virtual void YellowOn() + { + printf("Yellow On\n"); + } + virtual void RedOff() + { + printf("Red Off\n"); + } + virtual void RedOn() + { + printf("Red On\n"); + } + + virtual void EnableRedFlashMode() + { + printf("Setting Red Flash mode\n"); + } + + virtual void HSMDebug(char* msg) + { + printf("HSMDebug: %s\n",msg); + } +}; + +int main() +{ + printf("Press any key to simulate Error.\n"); + + MyStoplight s; + s.HSMConstruct(); + while ( s.HSMUpdate(0.1f) ) + { + Sleep(100); + } + return 0; +} + diff --git a/example/traffic/traffic.hsm b/example/traffic/traffic.hsm new file mode 100644 index 0000000..79a579f --- /dev/null +++ b/example/traffic/traffic.hsm @@ -0,0 +1,47 @@ + +Machine(stoplight,30) +{ + // perform power on self test + Entry(DoPOST); + + // first state is Red + Default(Red); + + // poll for a FAILURE event + Idle(CheckForError); + + // machine exits on FAILURE event + Terminate(FAILURE); + + // if machine exits, switch to Flash Mode + Exit(EnableRedFlashMode); + + // red light state + State(Red) + { + Entry(RedOn); + Exit(RedOff); + + Transition(5.0,Green); + } + + // green light state + State(Green) + { + Entry(GreenOn); + Exit(GreenOff); + + Transition(5,Yellow); + } + + // yellow light state + State(Yellow) + { + Entry(YellowOn); + Exit(YellowOff); + + Transition(1.000000,Red); + } +} + + diff --git a/hsmc.sln b/hsmc.sln new file mode 100644 index 0000000..d21500a --- /dev/null +++ b/hsmc.sln @@ -0,0 +1,32 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hsmc", "hsmc.vcproj", "{C5786482-145A-4B2D-8AA9-2E7CBB1EE69C}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 2 + SccProjectName0 = Perforce\u0020Project + SccLocalPath0 = . + SccProvider0 = MSSCCI:Perforce\u0020SCM + CanCheckoutShared = true + SolutionUniqueID = {BC171BD2-EB06-48AD-A2D5-D4F6E43EA3EF} + SccProjectUniqueName1 = hsmc.vcproj + SccLocalPath1 = . + CanCheckoutShared = true + EndGlobalSection + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {C5786482-145A-4B2D-8AA9-2E7CBB1EE69C}.Debug.ActiveCfg = Debug|Win32 + {C5786482-145A-4B2D-8AA9-2E7CBB1EE69C}.Debug.Build.0 = Debug|Win32 + {C5786482-145A-4B2D-8AA9-2E7CBB1EE69C}.Release.ActiveCfg = Release|Win32 + {C5786482-145A-4B2D-8AA9-2E7CBB1EE69C}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/hsmc.vcproj b/hsmc.vcproj new file mode 100644 index 0000000..61a734d --- /dev/null +++ b/hsmc.vcproj @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hsmc.vpj b/hsmc.vpj new file mode 100644 index 0000000..0ee8a34 --- /dev/null +++ b/hsmc.vpj @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hsmc.vpw b/hsmc.vpw new file mode 100644 index 0000000..32a1617 --- /dev/null +++ b/hsmc.vpw @@ -0,0 +1,6 @@ + + + + + + diff --git a/source/Makefile b/source/Makefile new file mode 100644 index 0000000..6f8f9e8 --- /dev/null +++ b/source/Makefile @@ -0,0 +1,77 @@ +# flags and libs +DEFS = +LIBS = + +# compiler and flags +CC = cc +CCFLAGS = -Wall -O3 -c +CXX = c++ +CXXFLAGS = $(CCFLAGS) +CPPFLAGS = + +# linker +LD = c++ +LDFLAGS = +STRIP = strip + +# misc programs +RM = rm -f +INSTALL = install +MKDEPEND = mkdepend +LEX = flex -f +YACC = yacc + +# our target and source code +TARGET = hsmc +SRCS = hsm-lexer.c hsm-parser.tab.c getopt.cpp main.cpp +OBJS = hsm-lexer.o hsm-parser.tab.o getopt.o main.o + +## +## + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) $(LIBS) -o $@ $(OBJS) + +hsm-parser.tab.h: \ + hsm.y + +hsm-parser.tab.c: hsm.y + $(YACC) -d -bhsm-parser hsm.y + +hsm-lexer.h: \ + hsm.l + +hsm-lexer.c: hsm.l + $(LEX) -ohsm-lexer.c hsm.l + +depend: + $(MKDEPEND) $(SRCS) + +clean: + $(RM) $(OBJS) $(TARGET) + +.cpp.o: + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(DEFS) $< -o $@ + +.c.o: + $(CC) $(CCFLAGS) $(CPPFLAGS) $(DEFS) $< -o $@ + + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +hsm-lexer.o: \ + hsm-parser.tab.h + +hsm-parser.o: \ + main.h + +main.o: \ + autofile.h \ + config.h \ + getopt.h \ + machine.h \ + main.h \ + state.h + diff --git a/source/autofile.h b/source/autofile.h new file mode 100644 index 0000000..211831a --- /dev/null +++ b/source/autofile.h @@ -0,0 +1,36 @@ +#ifndef __autofile_h__ +#define __autofile_h__ + +#include + +class AutoFILE +{ +public: + AutoFILE(char* filename, char* mode = "r") + { + f = fopen(filename,mode); + } + ~AutoFILE() + { + if ( Opened() ) + fclose(f); + } + operator FILE* () + { + return f; + } + bool Opened() + { + return f != (FILE*)0; + } + +private: + FILE* f; +}; + + + + + +#endif // __autofile_h__ + diff --git a/source/config.h b/source/config.h new file mode 100644 index 0000000..bf0bc56 --- /dev/null +++ b/source/config.h @@ -0,0 +1,127 @@ +#ifndef __config_h__ +#define __config_h__ + +#include +#include +#include "getopt.h" + +class Config +{ +public: + + std::string InFileName; + std::string OutCPPFileName; + std::string OutHFileName; + std::string IncludeName; + bool Debug; + bool Quiet; + bool PureVirtuals; + + void Usage() + { + printf( + "\n" + "\nHSMC - Hierarchical State Machine Compiler\n" + "\n" + "Usage: hsmc [-hdpq] [-o prefix] source_file\n" + "\n" + " -h this help\n" + " -d include debugging information\n" + " -p actions declared as pure virtual\n" + " -q quiet mode (only output errors)\n" + " -o prefix specify prefix for output files [prefix.cpp,prefix.h]\n" + " source_file HSM source file\n" + "\n" + ); + } + + bool ParseCommandLine(int argc, char* argv[]) + { + // reset defaults + InFileName = ""; + OutCPPFileName = ""; + OutHFileName = ""; + IncludeName = ""; + Debug = false; + Quiet = false; + PureVirtuals = false; + + // temporary + std::string prefix = ""; + + // parse command line + int ch; + while ( (ch = getopt(argc,argv,"hdpqo:")) != -1 ) + { + switch ( ch ) + { + case 'p': + PureVirtuals = true; + break; + + case 'q': + Quiet = true; + break; + + case 'd': + Debug = true; + break; + + case 'o': + prefix = optarg; + break; + + case 'h': + default: + Usage(); + return false; + } + } + + // check for input file + if ( (argc-optind) == 0 ) + { + printf("ERROR: no input file specified\n"); + Usage(); + return false; + } + else if ( (argc-optind) > 1 ) + { + printf("ERROR: multiple input files not allowed\n"); + Usage(); + return false; + } + + // got input file + InFileName = argv[optind]; + + // determine output prefix if it wasn't specified + if ( prefix == "" ) + { + // prefix NOT specified, let's get it from the base + prefix = InFileName.substr(0,InFileName.rfind('.')); + } + + // determine output files specified + OutCPPFileName = prefix + ".cpp"; + OutHFileName = prefix + ".h"; + + // strip up to any '/' or '\' + IncludeName = OutHFileName; + if ( OutHFileName.rfind('/') >= 0 ) + { + IncludeName = IncludeName.substr( IncludeName.rfind('/')+1 ); + } + if ( OutHFileName.rfind('\\') >= 0 ) + { + IncludeName = IncludeName.substr( IncludeName.rfind('\\')+1 ); + } + + // success + return true; + } +}; + + +#endif // __config_h__ + diff --git a/source/getopt.cpp b/source/getopt.cpp new file mode 100644 index 0000000..237fbdf --- /dev/null +++ b/source/getopt.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) + #if 0 + static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; + #endif + static const char rcsid[] = "$FreeBSD: src/lib/libc/stdlib/getopt.c,v 1.2 1999/12/17 01:52:15 jkh Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* +* getopt -- +* Parse argc/argv argument vector. +*/ +#if defined(__cplusplus) +extern "C" +#endif +int getopt(int nargc, char* const* nargv, const char* ostr) +{ + char *__progname = nargv[0]; + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + int ret; + + if ( optreset || !*place ) + { /* update scanning pointer */ + optreset = 0; + if ( optind >= nargc || *(place = nargv[optind]) != '-' ) + { + place = EMSG; + return(-1); + } + if ( place[1] && *++place == '-' ) + { /* found "--" */ + ++optind; + place = EMSG; + return(-1); + } + } /* option letter okay? */ + if ( (optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt)) ) + { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if ( optopt == (int)'-' ) + return(-1); + if ( !*place ) + ++optind; + if ( opterr && *ostr != ':' ) + (void)fprintf(stderr,"%s: illegal option -- %c\n", __progname, optopt); + return(BADCH); + } + if ( *++oli != ':' ) + { + /* don't need argument */ + optarg = NULL; + if ( !*place ) + { + ++optind; + } + } + else + { + /* need an argument */ + if ( *place ) + { + /* no white space */ + optarg = place; + } + else if ( nargc <= ++optind ) + { + /* no arg */ + place = EMSG; + if ( *ostr == ':' ) + ret = BADARG; + else + ret = BADCH; + if ( opterr ) + (void)fprintf(stderr,"%s: option requires an argument -- %c\n",__progname, optopt); + return(ret); + } + else + { + /* white space */ + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + return(optopt); /* dump back option letter */ +} + diff --git a/source/getopt.h b/source/getopt.h new file mode 100644 index 0000000..2304d6f --- /dev/null +++ b/source/getopt.h @@ -0,0 +1,20 @@ +#ifndef __getopt_h__ +#define __getopt_h__ + +extern int opterr; /* if error message should be printed */ +extern int optind; /* index into parent argv vector */ +extern int optopt; /* character checked for validity */ +extern int optreset; /* reset getopt */ +extern char *optarg; /* argument associated with option */ + +#if defined(__cplusplus) +extern "C" { +#endif + +int getopt(int nargc, char* const* nargv, const char* ostr); + +#if defined(__cplusplus) +} +#endif + +#endif // __getopt_h__ diff --git a/source/hsm-lexer.c b/source/hsm-lexer.c new file mode 100644 index 0000000..dc3e0c0 --- /dev/null +++ b/source/hsm-lexer.c @@ -0,0 +1,1684 @@ +#line 2 "hsm-lexer.c" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: //shared/tools/util/hsmc/current/source/hsm-lexer.c#1 $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 22 +#define YY_END_OF_BUFFER 23 +static yyconst short int yy_accept[79] = + { 0, + 0, 0, 23, 21, 1, 20, 7, 8, 3, 21, + 19, 4, 18, 18, 18, 18, 18, 18, 18, 18, + 5, 6, 1, 2, 19, 19, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 2, 19, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 14, 13, 18, 18, 18, 18, 18, 18, 12, 18, + 10, 18, 18, 16, 18, 18, 18, 18, 11, 9, + 18, 18, 18, 18, 17, 18, 15, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 4, + 5, 1, 1, 6, 1, 7, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1, 10, 1, + 1, 1, 1, 1, 11, 12, 13, 14, 15, 16, + 12, 17, 18, 12, 12, 19, 20, 21, 22, 12, + 12, 23, 24, 25, 26, 12, 12, 27, 28, 12, + 1, 1, 1, 1, 12, 1, 11, 12, 13, 14, + + 15, 16, 12, 17, 18, 12, 12, 19, 20, 21, + 22, 12, 12, 23, 24, 25, 26, 12, 12, 27, + 28, 12, 29, 1, 30, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[31] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 3, 1, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 1, 1 + } ; + +static yyconst short int yy_base[81] = + { 0, + 0, 0, 91, 92, 88, 92, 92, 92, 92, 81, + 24, 92, 75, 0, 72, 11, 72, 74, 59, 19, + 92, 92, 81, 0, 73, 28, 0, 56, 64, 54, + 60, 58, 63, 64, 51, 62, 0, 63, 53, 59, + 46, 43, 52, 49, 40, 44, 42, 40, 35, 32, + 0, 0, 41, 43, 39, 32, 34, 35, 0, 32, + 0, 31, 33, 0, 25, 34, 37, 22, 0, 0, + 21, 26, 26, 18, 0, 18, 0, 92, 33, 42 + } ; + +static yyconst short int yy_def[81] = + { 0, + 78, 1, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, + 78, 78, 78, 80, 78, 78, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 80, 78, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 0, 78, 78 + } ; + +static yyconst short int yy_nxt[123] = + { 0, + 4, 5, 6, 7, 8, 9, 4, 10, 11, 12, + 13, 14, 14, 15, 16, 14, 14, 17, 14, 18, + 14, 14, 14, 19, 20, 14, 14, 14, 21, 22, + 25, 30, 26, 35, 25, 27, 26, 31, 77, 76, + 75, 36, 37, 74, 37, 73, 72, 71, 70, 69, + 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, + 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, + 48, 38, 47, 46, 45, 44, 43, 42, 41, 40, + 39, 38, 23, 34, 33, 32, 29, 28, 24, 23, + 78, 3, 78, 78, 78, 78, 78, 78, 78, 78, + + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78 + } ; + +static yyconst short int yy_chk[123] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 16, 11, 20, 26, 79, 26, 16, 76, 74, + 73, 20, 80, 72, 80, 71, 68, 67, 66, 65, + 63, 62, 60, 58, 57, 56, 55, 54, 53, 50, + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, + 39, 38, 36, 35, 34, 33, 32, 31, 30, 29, + 28, 25, 23, 19, 18, 17, 15, 13, 10, 5, + 3, 78, 78, 78, 78, 78, 78, 78, 78, 78, + + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "hsm.l" +#define INITIAL 0 +#line 2 "hsm.l" + + +#include +#include +#include + +#include "hsm-parser.tab.h" + +int lineno = 1; + +void yyerror(char* s); + + +#line 427 "hsm-lexer.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 18 "hsm.l" + + + /* whitespace */ + +#line 583 "hsm-lexer.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 79 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 92 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 22 "hsm.l" +; /* skip whitespace */ + YY_BREAK +/* comments */ +case 2: +YY_RULE_SETUP +#line 28 "hsm.l" +; /* skip C++ comments */ + YY_BREAK +/* punctuation */ +case 3: +YY_RULE_SETUP +#line 33 "hsm.l" +{ return ','; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 34 "hsm.l" +{ return ';'; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 35 "hsm.l" +{ return '{'; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 36 "hsm.l" +{ return '}'; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 37 "hsm.l" +{ return '('; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 38 "hsm.l" +{ return ')'; } + YY_BREAK +/* keywords */ +case 9: +YY_RULE_SETUP +#line 43 "hsm.l" +{ return MACHINE; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 44 "hsm.l" +{ return STATE; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 45 "hsm.l" +{ return DEFAULT; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 46 "hsm.l" +{ return ENTRY; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 47 "hsm.l" +{ return IDLE; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 48 "hsm.l" +{ return EXIT; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 49 "hsm.l" +{ return TRANSITION; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 50 "hsm.l" +{ return ACTION; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 51 "hsm.l" +{ return TERMINATE; } + YY_BREAK +/* identifiers */ +case 18: +YY_RULE_SETUP +#line 56 "hsm.l" +{ if ( strlen(yytext) > 256 ) printf("%d: truncating symbol '%s' to 256 characters\n",lineno,yytext); strncpy(yylval.string,yytext,256); return IDENTIFIER; } + YY_BREAK +/* constants */ +case 19: +YY_RULE_SETUP +#line 61 "hsm.l" +{ yylval.constant = (float)atof(yytext); return CONSTANT; } + YY_BREAK +/* newlines, etc. */ +case 20: +YY_RULE_SETUP +#line 66 "hsm.l" +{ lineno++; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 67 "hsm.l" +; /* ignore */ + YY_BREAK +case 22: +YY_RULE_SETUP +#line 70 "hsm.l" +ECHO; + YY_BREAK +#line 782 "hsm-lexer.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 79 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 79 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 78); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 70 "hsm.l" + + + + +int yywrap() +{ + return 1; +} + +void yyerror(char* s) +{ + printf("\n%d: %s at %s\n", lineno, s, yytext); +} + + + + diff --git a/source/hsm-parser.tab.c b/source/hsm-parser.tab.c new file mode 100644 index 0000000..3abe7fe --- /dev/null +++ b/source/hsm-parser.tab.c @@ -0,0 +1,469 @@ +#ifndef lint +static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; +#endif +#define YYBYACC 1 +#define YYMAJOR 1 +#define YYMINOR 9 +#define yyclearin (yychar=(-1)) +#define yyerrok (yyerrflag=0) +#define YYRECOVERING (yyerrflag!=0) +#define YYPREFIX "yy" +#line 2 "hsm.y" + + +extern int yylex(); +extern void yyerror(char* s); + +#include "main.h" + +#line 11 "hsm.y" +typedef union +{ + char string[258]; + float constant; +} YYSTYPE; +#line 26 "hsm-parser.tab.c" +#define MACHINE 257 +#define STATE 258 +#define DEFAULT 259 +#define ENTRY 260 +#define IDLE 261 +#define EXIT 262 +#define TRANSITION 263 +#define ACTION 264 +#define TERMINATE 265 +#define IDENTIFIER 266 +#define CONSTANT 267 +#define YYERRCODE 256 +short yylhs[] = { -1, + 0, 0, 1, 3, 3, 4, 4, 5, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 2, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, +}; +short yylen[] = { 2, + 1, 2, 4, 1, 2, 1, 1, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 6, 4, 4, + 4, 4, 4, 6, 6, 6, 6, 4, +}; +short yydefred[] = { 0, + 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 5, 0, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 19, 20, 21, 22, 23, 0, + 0, 0, 0, 28, 8, 0, 0, 0, 0, 24, + 26, 25, 27, +}; +short yydgoto[] = { 2, + 3, 4, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, +}; +short yysindex[] = { -251, + -33, -251, 0, -106, -248, 0, -249, -25, -20, -19, + -18, -17, -15, -14, -13, -12, -125, 0, 0, 0, + -99, -30, -29, -28, -27, -26, -24, -23, -22, -21, + -233, -227, -226, -225, -224, -223, -264, -262, -222, 0, + 0, -249, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 5, 7, 8, 9, 10, 11, 12, 13, + 14, 18, -117, 0, 0, 0, 0, 0, 0, -214, + -213, -212, -206, 0, 0, 20, 21, 22, 23, 0, + 0, 0, 0, +}; +short yyrindex[] = { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; +short yygindex[] = { 0, + 63, 0, 24, -16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; +#define YYTABLESIZE 148 +short yytable[] = { 40, + 41, 58, 59, 60, 61, 1, 5, 75, 9, 10, + 11, 12, 13, 14, 15, 16, 7, 8, 31, 32, + 33, 34, 35, 42, 36, 37, 38, 39, 43, 44, + 45, 46, 47, 52, 48, 49, 50, 51, 53, 54, + 55, 56, 57, 62, 64, 65, 41, 66, 67, 68, + 69, 76, 77, 78, 70, 71, 72, 73, 74, 79, + 80, 81, 82, 83, 6, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 10, 11, 12, 13, 14, 15, 16, + 9, 10, 11, 12, 13, 14, 15, 16, +}; +short yycheck[] = { 125, + 17, 266, 267, 266, 267, 257, 40, 125, 258, 259, + 260, 261, 262, 263, 264, 265, 123, 266, 44, 40, + 40, 40, 40, 123, 40, 40, 40, 40, 59, 59, + 59, 59, 59, 267, 59, 59, 59, 59, 266, 266, + 266, 266, 266, 266, 41, 41, 63, 41, 41, 41, + 41, 266, 266, 266, 44, 44, 44, 44, 41, 266, + 41, 41, 41, 41, 2, 42, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 258, 259, 260, 261, 262, 263, 264, 265, + 258, 259, 260, 261, 262, 263, 264, 265, +}; +#define YYFINAL 2 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 267 +#if YYDEBUG +char *yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,"';'",0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"MACHINE", +"STATE","DEFAULT","ENTRY","IDLE","EXIT","TRANSITION","ACTION","TERMINATE", +"IDENTIFIER","CONSTANT", +}; +char *yyrule[] = { +"$accept : machines", +"machines : machine", +"machines : machines machine", +"machine : machine_decl '{' state_items '}'", +"state_items : state_item", +"state_items : state_items state_item", +"state_item : state", +"state_item : statement", +"state : state_decl '{' state_items '}'", +"statement : default ';'", +"statement : entry ';'", +"statement : idle ';'", +"statement : exit ';'", +"statement : transition ';'", +"statement : action ';'", +"statement : timetransition ';'", +"statement : timeaction ';'", +"statement : terminate ';'", +"machine_decl : MACHINE '(' IDENTIFIER ',' CONSTANT ')'", +"state_decl : STATE '(' IDENTIFIER ')'", +"default : DEFAULT '(' IDENTIFIER ')'", +"entry : ENTRY '(' IDENTIFIER ')'", +"idle : IDLE '(' IDENTIFIER ')'", +"exit : EXIT '(' IDENTIFIER ')'", +"transition : TRANSITION '(' IDENTIFIER ',' IDENTIFIER ')'", +"action : ACTION '(' IDENTIFIER ',' IDENTIFIER ')'", +"timetransition : TRANSITION '(' CONSTANT ',' IDENTIFIER ')'", +"timeaction : ACTION '(' CONSTANT ',' IDENTIFIER ')'", +"terminate : TERMINATE '(' IDENTIFIER ')'", +}; +#endif +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 500 +#define YYMAXDEPTH 500 +#endif +#endif +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +short yyss[YYSTACKSIZE]; +YYSTYPE yyvs[YYSTACKSIZE]; +#define yystacksize YYSTACKSIZE +#define YYABORT goto yyabort +#define YYREJECT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +int +yyparse() +{ + register int yym, yyn, yystate; +#if YYDEBUG + register char *yys; + extern char *getenv(); + + if (yys = getenv("YYDEBUG")) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if (yyn = yydefred[yystate]) goto yyreduce; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, shifting to state %d\n", + YYPREFIX, yystate, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#ifdef lint + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, error recovery shifting\ + to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: error recovery discarding state %d\n", + YYPREFIX, *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, error recovery discards token %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, reducing by rule %d (%s)\n", + YYPREFIX, yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 3: +#line 37 "hsm.y" +{ + parseEndMachine(); + } +break; +case 8: +#line 51 "hsm.y" +{ + parseEndState(); + } +break; +case 18: +#line 68 "hsm.y" +{ + parseBeginMachine(yyvsp[-3].string,(int)yyvsp[-1].constant); + } +break; +case 19: +#line 74 "hsm.y" +{ + parseBeginState(yyvsp[-1].string); + } +break; +case 20: +#line 80 "hsm.y" +{ + parseDefault(yyvsp[-1].string); + } +break; +case 21: +#line 86 "hsm.y" +{ + parseEntry(yyvsp[-1].string); + } +break; +case 22: +#line 92 "hsm.y" +{ + parseIdle(yyvsp[-1].string); + } +break; +case 23: +#line 98 "hsm.y" +{ + parseExit(yyvsp[-1].string); + } +break; +case 24: +#line 104 "hsm.y" +{ + parseTransition(yyvsp[-3].string,yyvsp[-1].string); + } +break; +case 25: +#line 110 "hsm.y" +{ + parseAction(yyvsp[-3].string,yyvsp[-1].string); + } +break; +case 26: +#line 116 "hsm.y" +{ + parseTimeTransition(yyvsp[-3].constant,yyvsp[-1].string); + } +break; +case 27: +#line 122 "hsm.y" +{ + parseTimeAction(yyvsp[-3].constant,yyvsp[-1].string); + } +break; +case 28: +#line 128 "hsm.y" +{ + parseTerminate(yyvsp[-1].string); + } +break; +#line 414 "hsm-parser.tab.c" + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state 0 to\ + state %d\n", YYPREFIX, YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state %d \ +to state %d\n", YYPREFIX, *yyssp, yystate); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} diff --git a/source/hsm-parser.tab.h b/source/hsm-parser.tab.h new file mode 100644 index 0000000..c95c397 --- /dev/null +++ b/source/hsm-parser.tab.h @@ -0,0 +1,17 @@ +#define MACHINE 257 +#define STATE 258 +#define DEFAULT 259 +#define ENTRY 260 +#define IDLE 261 +#define EXIT 262 +#define TRANSITION 263 +#define ACTION 264 +#define TERMINATE 265 +#define IDENTIFIER 266 +#define CONSTANT 267 +typedef union +{ + char string[258]; + float constant; +} YYSTYPE; +extern YYSTYPE yylval; diff --git a/source/hsm.l b/source/hsm.l new file mode 100644 index 0000000..6ea1c4e --- /dev/null +++ b/source/hsm.l @@ -0,0 +1,86 @@ +%{ + + +#include +#include +#include + +#include "hsm-parser.tab.h" + +int lineno = 1; + +void yyerror(char* s); + + +%} + + +%% + + /* whitespace */ + +[ \t]+ ; /* skip whitespace */ + + + + /* comments */ + +"//".* ; /* skip C++ comments */ + + + /* punctuation */ + +"," { return ','; } +";" { return ';'; } +"{" { return '{'; } +"}" { return '}'; } +"(" { return '('; } +")" { return ')'; } + + + /* keywords */ + +[Mm][Aa][Cc][Hh][Ii][Nn][Ee] { return MACHINE; } +[Ss][Tt][Aa][Tt][Ee] { return STATE; } +[Dd][Ee][Ff][Aa][Uu][Ll][Tt] { return DEFAULT; } +[Ee][Nn][Tt][Rr][Yy] { return ENTRY; } +[Ii][Dd][Ll][Ee] { return IDLE; } +[Ee][Xx][Ii][Tt] { return EXIT; } +[Tt][Rr][Aa][Nn][Ss][Ii][Tt][Ii][Oo][Nn] { return TRANSITION; } +[Aa][Cc][Tt][Ii][Oo][Nn] { return ACTION; } +[Tt][Ee][Rr][Mm][Ii][Nn][Aa][Tt][Ee] { return TERMINATE; } + + + /* identifiers */ + +[a-zA-Z_][a-zA-Z_0-9]* { if ( strlen(yytext) > 256 ) printf("%d: truncating symbol '%s' to 256 characters\n",lineno,yytext); strncpy(yylval.string,yytext,256); return IDENTIFIER; } + + + /* constants */ + +[0-9]+\.?[0-9]* { yylval.constant = (float)atof(yytext); return CONSTANT; } + + + /* newlines, etc. */ + +\n { lineno++; } +. ; /* ignore */ + + +%% + + + +int yywrap() +{ + return 1; +} + +void yyerror(char* s) +{ + printf("\n%d: %s at %s\n", lineno, s, yytext); +} + + + + diff --git a/source/hsm.y b/source/hsm.y new file mode 100644 index 0000000..9dd5300 --- /dev/null +++ b/source/hsm.y @@ -0,0 +1,135 @@ +%{ + + +extern int yylex(); +extern void yyerror(char* s); + +#include "main.h" + +%} + +%union +{ + char string[258]; + float constant; +} + +%token MACHINE +%token STATE +%token DEFAULT +%token ENTRY +%token IDLE +%token EXIT +%token TRANSITION +%token ACTION +%token TERMINATE + +%token IDENTIFIER +%token CONSTANT + +%% + +machines: machine + | machines machine + ; + +machine: machine_decl '{' state_items '}' + { + parseEndMachine(); + } + ; + +state_items: state_item + | state_items state_item + ; + +state_item: state + | statement + ; + +state: state_decl '{' state_items '}' + { + parseEndState(); + } + ; + +statement: default ';' + | entry ';' + | idle ';' + | exit ';' + | transition ';' + | action ';' + | timetransition ';' + | timeaction ';' + | terminate ';' + ; + +machine_decl: MACHINE '(' IDENTIFIER ',' CONSTANT ')' + { + parseBeginMachine($3,(int)$5); + } + ; + +state_decl: STATE '(' IDENTIFIER ')' + { + parseBeginState($3); + } + ; + +default: DEFAULT '(' IDENTIFIER ')' + { + parseDefault($3); + } + ; + +entry: ENTRY '(' IDENTIFIER ')' + { + parseEntry($3); + } + ; + +idle: IDLE '(' IDENTIFIER ')' + { + parseIdle($3); + } + ; + +exit: EXIT '(' IDENTIFIER ')' + { + parseExit($3); + } + ; + +transition: TRANSITION '(' IDENTIFIER ',' IDENTIFIER ')' + { + parseTransition($3,$5); + } + ; + +action: ACTION '(' IDENTIFIER ',' IDENTIFIER ')' + { + parseAction($3,$5); + } + ; + +timetransition: TRANSITION '(' CONSTANT ',' IDENTIFIER ')' + { + parseTimeTransition($3,$5); + } + ; + +timeaction: ACTION '(' CONSTANT ',' IDENTIFIER ')' + { + parseTimeAction($3,$5); + } + ; + +terminate: TERMINATE '(' IDENTIFIER ')' + { + parseTerminate($3); + } + ; + + + + diff --git a/source/hsmc.dev b/source/hsmc.dev new file mode 100644 index 0000000..b99642e --- /dev/null +++ b/source/hsmc.dev @@ -0,0 +1,159 @@ +[Project] +FileName=hsmc.dev +Name=hsmc +UnitCount=11 +Type=1 +Ver=1 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=1 +Icon= +ExeOutput= +ObjectOutput= +OverrideOutput=0 +OverrideOutputName=hsmc.exe +HostApplication= +Folders= +CommandLine=../example/parsetest/parsetest.hsm +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000001000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=autofile.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=config.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=getopt.cpp +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=getopt.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=hsm-lexer.c +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=hsm-parser.tab.c +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=hsm-parser.tab.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=machine.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=main.cpp +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=main.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=state.h +CompileCpp=1 +Folder=hsmc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + diff --git a/source/machine.h b/source/machine.h new file mode 100644 index 0000000..9b4fd81 --- /dev/null +++ b/source/machine.h @@ -0,0 +1,488 @@ +#ifndef __machine_h__ +#define __machine_h__ + + +#include +#include +#include +#include + +#include "state.h" + +class Machine +{ +public: + + // data + std::string name; + + std::vector states; + std::map statemap; + + std::set event_refs; + std::set state_refs; + std::set action_refs; + + // construction + Machine(); + + // add data + int AddState(std::string name); + int EndState(); + bool AddDefault(std::string state); + bool AddEntry(std::string action); + bool AddIdle(std::string action); + bool AddExit(std::string action); + bool AddTransition(char* event,char* state); + bool AddAction(char* event,char* action); + bool AddTimeTransition(float time,char* state); + bool AddTimeAction(float time,char* action); + bool AddTerminate(char* event); + + // get data + std::string CurStateName(); + int GetMaxDepth(); + int GetTimerDepth(); + + // finalize machine + bool EndMachine(); + + // settings + void SetQueueSize(int size); + int GetQueueSize(); + +private: + + int curstate; + int maxdepth; + int depth; + int timerdepth; + int queuesize; + + int CountTimers(int sid); + + bool Validate(); +}; + + +// initialize a machine +Machine::Machine() +{ + // set current state to invalid + curstate = -1; + + // default depth + maxdepth = 0; + depth = 0; +} + +int Machine::AddState(std::string name) +{ + // make sure this isn't a duplicate state + if ( statemap.find(name) != statemap.end() ) + { + return -1; + } + + // figure out our new state id + int id = (int)states.size(); + + // add this state to our name -> id map + statemap[name] = id; + + // tell parent about this new child state + if ( curstate >= 0 ) + { + states[curstate].child.push_back(id); + } + + // create new state + State s; + s.name = name; + + // tell current state about parent + s.parent = curstate; + + // add state to list and make current + states.push_back(s); + + // record depth + depth++; + if ( depth > maxdepth ) + { + maxdepth = depth; + } + + // make this new state the current state + curstate = id; + return curstate; +} + +int Machine::EndState() +{ + // dec depth + depth--; + + // move curstate to parent + if ( curstate >= 0 ) + { + curstate = states[curstate].parent; + } + return curstate; +} + +bool Machine::AddDefault(std::string state) +{ + if ( curstate < 0 ) + { + return false; + } + else if ( states[curstate].defaultstate != "" ) + { + // default state already set for this state + return false; + } + else + { + states[curstate].defaultstate = state; + state_refs.insert(state); + return true; + } +} + +bool Machine::AddEntry(std::string action) +{ + if ( curstate < 0 ) + { + return false; + } + + // add entry action and reference + states[curstate].entry.push_back(action); + action_refs.insert(action); + + return true; +} + +bool Machine::AddIdle(std::string action) +{ + if ( curstate < 0 ) + { + return false; + } + + // add idle action and reference + states[curstate].idle.push_back(action); + action_refs.insert(action); + + return true; +} + +bool Machine::AddExit(std::string action) +{ + if ( curstate < 0 ) + { + return false; + } + + // add exit action and reference + states[curstate].exit.push_back(action); + action_refs.insert(action); + + return true; +} + +bool Machine::AddTransition(char* event,char* state) +{ + if ( curstate < 0 ) + { + return false; + } + + // make certain a transition doesn't already exist for this event + if ( states[curstate].transition.find(event) != states[curstate].transition.end() ) + { + // transition already exists for this event + return false; + } + + // add transition + states[curstate].transition[event] = state; + + // add references + event_refs.insert(event); + state_refs.insert(state); + + return true; +} + +bool Machine::AddAction(char* event,char* action) +{ + if ( curstate < 0 ) + { + return false; + } + + // add action + states[curstate].action.insert( std::pair(event,action) ); + + // add references + event_refs.insert(event); + action_refs.insert(action); + + return true; +} + +bool Machine::AddTimeTransition(float time,char* state) +{ + if ( curstate < 0 ) + { + return false; + } + + // add timeout + states[curstate].timetransition.insert( std::pair(time,state) ); + + // add references + state_refs.insert(state); + + return true; +} + +bool Machine::AddTimeAction(float time,char* action) +{ + if ( curstate < 0 ) + { + return false; + } + + // add timeout + states[curstate].timeaction.insert( std::pair(time,action) ); + + // add references + action_refs.insert(action); + + return true; +} + +bool Machine::AddTerminate(char* event) +{ + if ( curstate < 0 ) + { + return false; + } + else if ( states[curstate].terminate.find(event) != states[curstate].terminate.end() ) + { + // already exists + return false; + } + + // add terminate + states[curstate].terminate.insert(event); + + // add reference + event_refs.insert(event); + + return true; +} + +std::string Machine::CurStateName() +{ + if ( curstate < 0 ) + { + return ""; + } + else + { + return states[curstate].name; + } +} + +int Machine::GetMaxDepth() +{ + return maxdepth; +} + +int Machine::GetTimerDepth() +{ + return timerdepth; +} + +bool Machine::EndMachine() +{ + // now let's validate it + return Validate(); +} + +int Machine::CountTimers(int sid) +{ + int count = 0; + while ( sid >= 0 ) + { + count += (int)states[sid].timers.size(); + sid = states[sid].parent; + } + + return count; +} + + +bool Machine::Validate() +{ + bool ok = true; + + // make sure all referenced states are defined + for ( std::set::iterator it = state_refs.begin(); it != state_refs.end(); it++ ) + { + if ( statemap.find( *it ) == statemap.end() ) + { + ok = false; + printf( + "Error: State '%s' referenced but not defined in Machine '%s'\n", + (*it).c_str(),name.c_str()); + } + } + + // make sure events listed as terminate are not also listed in actions or transitions + for ( std::vector::iterator it = states.begin(); it != states.end(); it++ ) + { + // for convenience + State& s = (*it); + + // check each "terminate event and make sure it's not in the action or transition list + for ( std::set::iterator term = s.terminate.begin(); term != s.terminate.end(); term++ ) + { + // look in action & transitions lists + if ( s.action.find(*term) != s.action.end() || s.transition.find(*term) != s.transition.end() ) + { + ok = false; + printf( + "Error: Terminate event '%s' is not unique in State '%s', Machine '%s'\n", + (*term).c_str(), s.name.c_str(), name.c_str() + ); + } + } + } + + // make sure all of the state names are NOT event names + for ( std::vector::iterator it = states.begin(); it != states.end(); it++ ) + { + State& s = (*it); + + // look for this name in the event list + if ( event_refs.find(s.name) != event_refs.end() ) + { + ok = false; + printf( + "Error: State-Event name collision on '%s' in Machine '%s'\n", + s.name.c_str(), + name.c_str() + ); + } + } + + // make certain that no timed actions or transitions exist after shortest timed + // transition in each state + for ( std::vector::iterator it = states.begin(); it != states.end(); it++ ) + { + State& s = (*it); + + // if no timed transitions we're done + if ( s.timetransition.size() == 0 ) + { + continue; + } + + // find shortest timed transition + std::multimap::iterator ttit = s.timetransition.begin(); + float shorttime = (*ttit).first; + std::string shorttrans = (*ttit).second; + + // now iterate timed transitions and warn about remaining + for ( ttit++; ttit != s.timetransition.end(); ttit++ ) + { + printf( + "Error: Timed Transition '%s/%f' superceded by '%s/%f' in State '%s', Machine '%s'\n", + (*ttit).second.c_str(), + (*ttit).first, + shorttrans.c_str(), + shorttime, + s.name.c_str(), + name.c_str() + ); + s.timetransition.erase(ttit); + ok = false; + } + + // iterate through timed actions and warn about anything over + std::multimap::iterator tait; + for ( tait = s.timeaction.begin(); tait != s.timeaction.end(); tait++ ) + { + if ( (*tait).first >= shorttime ) + { + printf( + "Error: Timed Action '%s/%f' superceded by '%s/%f' in State '%s', Machine '%s'\n", + (*tait).second.c_str(), + (*tait).first, + shorttrans.c_str(), + shorttime, + s.name.c_str(), + name.c_str() + ); + s.timeaction.erase(tait); + ok = false; + } + } + } + + // now assign timers (value+id) for each state + for ( std::vector::iterator it = states.begin(); it != states.end(); it++ ) + { + State& s = (*it); + + // now count up timer values for this state + std::set timervalues; + for ( std::multimap::iterator ttit = s.timetransition.begin(); ttit != s.timetransition.end(); ttit++ ) + { + timervalues.insert( (*ttit).first ); + } + for ( std::multimap::iterator tait = s.timeaction.begin(); tait != s.timeaction.end(); tait++ ) + { + timervalues.insert( (*tait).first ); + } + + // assign timer id's to values + int ptimers = CountTimers(s.parent); + for ( std::set::iterator myit = timervalues.begin(); myit != timervalues.end(); myit++ ) + { + s.timers[ptimers++] = *myit; + } + } + + // determine max timer depth + timerdepth = 0; + for ( unsigned int i=0;i timerdepth ) + { + timerdepth = depth; + } + } + + return ok; +} + +void Machine::SetQueueSize(int size) +{ + queuesize = size; +} + +int Machine::GetQueueSize() +{ + return queuesize; +} + +#endif // __machine_h__ + + diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 0000000..4561cea --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,1387 @@ +#include +#include + +#include +#include +#include +#include + +#include "getopt.h" +#include "main.h" +#include "autofile.h" +#include "machine.h" +#include "state.h" +#include "config.h" + + +// +// globals +// + +std::vector gMachines; +int gCurMachine; +Config gConfig; +int gErrors = 0; + + + +// +// parser interface functions +// + +extern "C" FILE* yyin; + +extern "C" void parseEndMachine() +{ + if ( !gMachines[gCurMachine].EndMachine() ) + { + gErrors++; + } +} + +extern "C" void parseEndState() +{ + gMachines[gCurMachine].EndState(); +} + +extern "C" void parseBeginMachine(char* name, int eventsize) +{ + // validate event size + if ( eventsize <= 0 ) + { + extern int lineno; + printf("%d: Invalid event queue size for Machine '%s'\n", + lineno, + name); + gErrors++; + } + + // create new machine + Machine m; + m.name = name; + m.SetQueueSize(eventsize); + + // create top state + m.AddState("TOPSTATE"); + + // add machine to list + gMachines.push_back(m); + + // update current machine id + gCurMachine = (int)gMachines.size() - 1; +} + +extern "C" void parseBeginState(char* name) +{ + if ( gMachines[gCurMachine].AddState(name) < 0 ) + { + extern int lineno; + printf("%d: State '%s' was previously defined\n", + lineno, + name); + gErrors++; + } +} + +extern "C" void parseDefault(char* state) +{ + if ( !gMachines[gCurMachine].AddDefault(state) ) + { + extern int lineno; + printf("%d: multiple Default states defined in State '%s'\n", + lineno, + (gMachines[gCurMachine].CurStateName()).c_str()); + gErrors++; + } +} + +extern "C" void parseEntry(char* action) +{ + gMachines[gCurMachine].AddEntry(action); +} + +extern "C" void parseIdle(char* action) +{ + gMachines[gCurMachine].AddIdle(action); +} + +extern "C" void parseExit(char* action) +{ + gMachines[gCurMachine].AddExit(action); +} + +extern "C" void parseTransition(char* event,char* state) +{ + if ( !gMachines[gCurMachine].AddTransition(event,state) ) + { + extern int lineno; + printf("%d: multiple Transition's on '%s' defined in '%s'\n", + lineno, + event, + (gMachines[gCurMachine].CurStateName()).c_str()); + gErrors++; + } +} + +extern "C" void parseAction(char* event,char* action) +{ + gMachines[gCurMachine].AddAction(event,action); +} + +extern "C" void parseTimeTransition(float time,char* state) +{ + gMachines[gCurMachine].AddTimeTransition(time,state); +} + +extern "C" void parseTimeAction(float time,char* action) +{ + gMachines[gCurMachine].AddTimeAction(time,action); +} + +extern "C" void parseTerminate(char* event) +{ + if ( !gMachines[gCurMachine].AddTerminate(event) ) + { + extern int lineno; + printf("%d: multiple Terminate's on '%s' defined in '%s'\n", + lineno, + event, + (gMachines[gCurMachine].CurStateName()).c_str()); + gErrors++; + } +} + + + +// +// output functions +// + +void OutputEvents(FILE* f, Machine& m) +{ + fprintf(f, + "\tenum\n" + "\t{\n" + ); + bool first = true; + for ( std::set::iterator it = m.event_refs.begin(); it != m.event_refs.end(); it++ ) + { + fprintf(f,"\t\t%s%s,\n",(*it).c_str(), first?" = 0":""); + first = false; + } + fprintf(f, + "\n" + "\t\t___HSM_NUM_EVENTS___\n" + "\t};\n\n"); +} + +void OutputStateIDs(FILE* f, Machine& m) +{ + fprintf(f, + "\tenum\n" + "\t{\n" + ); + bool first = true; + for ( std::vector::iterator it = m.states.begin(); it != m.states.end(); it++ ) + { + fprintf(f,"\t\t%s%s,\n",(*it).name.c_str(), first?" = 0":""); + first = false; + } + fprintf(f, + "\n" + "\t\t___HSM_NUM_STATES___\n" + "\t};\n\n"); +} + +void OutputPrivateEvents(FILE* f, Machine& m) +{ + // header + fprintf(f, + "\tenum\n" + "\t{\n" + "\t\t___HSM_ENTRY___ = ___HSM_NUM_EVENTS___,\n" + "\t\t___HSM_IDLE___,\n" + "\t\t___HSM_EXIT___,\n" + "\t\t___HSM_ELICIT_INITIAL_TRANSITION___,\n" + "\t\t___HSM_ELICIT_PARENT___,\n" + ); + + // private timer events + for ( int i=0;i::iterator it = m.action_refs.begin(); it != m.action_refs.end(); it++ ) + { + fprintf(f,"\tvirtual void %s()%s;\n",(*it).c_str(),gConfig.PureVirtuals ? " = 0" : ""); + } + fprintf(f,"\n"); +} + +void OutputActions(FILE* f, Machine& m) +{ + fprintf(f, + "//\n" + "// actions (must be overridden)\n" + "//\n" + ); + + for ( std::set::iterator it = m.action_refs.begin(); it != m.action_refs.end(); it++ ) + { + fprintf(f,"void %s::%s()\n",m.name.c_str(),(*it).c_str()); + fprintf(f, + "{\n" + "\t// empty\n" + "}\n\n" + ); + } +} + +void OutputStateProtos(FILE* f, Machine& m, int s) +{ + static int indent = 0; + + fprintf(f,"\tint %*s___HSMSTATE_%s___(int event);\n",indent*4,"",m.states[s].name.c_str()); + + indent++; + for ( unsigned int i=0;i::iterator it = m.states.begin(); it != m.states.end(); it++ ) + { + State& s = (*it); + std::vector null_events; + + // header + fprintf(f, + "//\n" + "// STATE: %s::%s\n" + "//\n" + "int %s::___HSMSTATE_%s___(int event)\n" + "{\n" + "\tswitch (event)\n" + "\t{\n", + m.name.c_str(),s.name.c_str(), + m.name.c_str(),s.name.c_str()); + + fprintf(f, + "\t\t// internal events\n\n" + ); + + // entry + fprintf(f, + "\t\tcase ___HSM_ENTRY___:\n" + ); + if ( gConfig.Debug ) + { + fprintf(f, + "\t\t\t___HSM_DEBUG___(\"Entering %s\");\n", + s.name.c_str() + ); + } + for ( std::map::iterator timeit = s.timers.begin(); timeit != s.timers.end(); timeit++ ) + { + fprintf(f, + "\t\t\t___HSM_START_TIMER___(%d,%0.7ff);\n", + (*timeit).first, + (*timeit).second + ); + } + for ( unsigned int i=0;i 0 ) + { + fprintf(f, + "\t\tcase ___HSM_IDLE___:\n" + ); + for ( unsigned int i=0;i::iterator timeit = s.timers.begin(); timeit != s.timers.end(); timeit++ ) + { + fprintf(f, + "\t\t\t___HSM_STOP_TIMER___(%d);\n", + (*timeit).first + ); + } + for ( unsigned int i=0;i 0 ) + { + fprintf(f, + "\t\t// timer events\n\n" + ); + for ( std::map::iterator timeit = s.timers.begin(); timeit != s.timers.end(); timeit++ ) + { + // which timer + fprintf(f, + "\t\tcase ___HSM_TIMER_%d___:\n", + (*timeit).first + ); + + // all actions with this time + for ( std::multimap::iterator acit = s.timeaction.begin(); acit != s.timeaction.end(); acit++ ) + { + if ( (*acit).first == (*timeit).second ) + { + // print debug info on action + if ( gConfig.Debug ) + { + fprintf(f, + "\t\t\t___HSM_DEBUG___(\"[TIMER EVENT]: %s()\");\n", + (*acit).second.c_str() + ); + } + + // call timer action + fprintf(f, + "\t\t\t%s();\n", + (*acit).second.c_str() + ); + } + } + + // any transition with this time? + for ( std::multimap::iterator trit = s.timetransition.begin(); trit != s.timetransition.end(); trit++ ) + { + if ( (*trit).first == (*timeit).second ) + { + // print debug info on transition + if ( gConfig.Debug ) + { + fprintf(f, + "\t\t\t___HSM_DEBUG___(\"[TIMER EVENT]: %s -> %s\");\n", + s.name.c_str(), + (*trit).second.c_str() + ); + } + + // do the transition + fprintf(f, + "\t\t\t___HSM_TRANSITION___(%s);\n", + (*trit).second.c_str() + ); + break; // only ONE transition allowed; should never happen, but be safe + } + } + + // return event handled + fprintf(f, + "\t\t\treturn ___HSM_NULL_STATE___;\n" + "\n" + ); + } + } + + // user events + if ( s.terminate.size() > 0 || s.transition.size() > 0 || s.action.size() > 0 ) + { + fprintf(f, + "\t\t// user events\n\n" + ); + } + + // terminate's if they exist + for ( std::set::iterator it = s.terminate.begin(); it != s.terminate.end(); it++ ) + { + fprintf(f, + "\t\tcase %s:\n", + (*it).c_str() + ); + } + if ( s.terminate.size() > 0 ) + { + // print debug info on terminal event + if ( gConfig.Debug ) + { + fprintf(f, + "\t\t\t___HSM_DEBUG___(\"[TERMINAL EVENT]: %s -> [HSM TERMINATION]\");\n", + s.name.c_str() + ); + } + + // terminate + fprintf(f, + "\t\t\t___HSM_STOP_MACHINE___();\n" + "\t\t\treturn ___HSM_TERMINAL_STATE___;\n" + "\n" + ); + } + + // transition's if they exist + for ( std::map::iterator it = s.transition.begin(); it != s.transition.end(); it++ ) + { + fprintf(f, + "\t\tcase %s:\n", + (*it).first.c_str() + ); + + // see if this event is used in any actions + for ( std::multimap::iterator tit = s.action.lower_bound((*it).first); tit != s.action.upper_bound((*it).first); tit++ ) + { + // print debug info on action + if ( gConfig.Debug ) + { + fprintf(f, + "\t\t\t___HSM_DEBUG___(\"%s: %s()\");\n", + (*it).first.c_str(), + (*tit).second.c_str() + ); + } + + // call action + fprintf(f, + "\t\t\t%s();\n", + (*tit).second.c_str() + ); + + } + + // print debug info on transition + if ( gConfig.Debug ) + { + fprintf(f, + "\t\t\t___HSM_DEBUG___(\"%s: %s -> %s\");\n", + (*it).first.c_str(), + s.name.c_str(), + (*it).second.c_str() + ); + } + + // now the transition + fprintf(f, + "\t\t\t___HSM_TRANSITION___(%s);\n" + "\t\t\treturn ___HSM_NULL_STATE___;\n\n", + (*it).second.c_str() + ); + } + + // actions if they exist + for ( std::multimap::iterator it = s.action.begin(); it != s.action.end(); it++ ) + { + // store off for ease of typing + std::string event = (*it).first; + + // did this action have a transition too? + if ( s.transition.find(event) == s.transition.end() ) + { + // how many actions associated with this event? + int count = (int)s.action.count(event); + + // print event + fprintf(f, + "\t\tcase %s:\n", + event.c_str() + ); + + for ( int i=0;i= 0 ? m.states[s.parent].name.c_str() : "___HSM_NULL_STATE___" + ); + + // footer + fprintf(f, + "\t}\n" + "}\n" + "\n" + ); + } +} + +void OutputStateTable(FILE* f, Machine& m) +{ + fprintf(f, + "%s::___HSMSTATE_FUNC___ %s::___HSM_STATE_TAB___[___HSM_NUM_STATES___] = \n" + "{\n", + m.name.c_str(),m.name.c_str() + ); + + for ( unsigned int i=0;i\n" + "\tclass StaticQueue\n" + "\t{\n" + "\tpublic:\n" + "\n" + "\t\tStaticQueue()\n" + "\t\t{\n" + "\t\t\tclear();\n" + "\t\t}\n" + "\n" + "\t\tvoid clear()\n" + "\t\t{\n" + "\t\t\tfirst = 0;\n" + "\t\t\tlast = -1;\n" + "\n" + "\t\t\tcursize = 0;\n" + "\t\t}\n" + "\n" + "\t\tbool put(T x)\n" + "\t\t{\n" + "\t\t\tif ( size() < N )\n" + "\t\t\t{\n" + "\t\t\t\tincrement(last);\n" + "\t\t\t\tdata[last] = x;\n" + "\t\t\t\tcursize++;\n" + "\t\t\t\treturn true;\n" + "\t\t\t}\n" + "\t\t\telse\n" + "\t\t\t{\n" + "\t\t\t\treturn false;\n" + "\t\t\t}\n" + "\t\t}\n" + "\n" + "\t\tbool get(T& x)\n" + "\t\t{\n" + "\t\t\tif ( size() > 0 )\n" + "\t\t\t{\n" + "\t\t\t\tx = data[first];\n" + "\t\t\t\tincrement(first);\n" + "\t\t\t\tcursize--;\n" + "\t\t\t\treturn true;\n" + "\t\t\t}\n" + "\t\t\telse\n" + "\t\t\t{\n" + "\t\t\t\treturn false;\n" + "\t\t\t}\n" + "\t\t}\n" + "\n" + "\t\tunsigned int size() const\n" + "\t\t{\n" + "\t\t\treturn cursize;\n" + "\t\t}\n" + "\n" + "\t\tbool IsEmpty() const\n" + "\t\t{\n" + "\t\t\treturn size() == 0;\n" + "\t\t}\n" + "\n" + "\t\tbool IsFull() const\n" + "\t\t{\n" + "\t\t\treturn size() == N;\n" + "\t\t}\n" + "\n" + "\tprivate:\n" + "\n" + "\t\tT data[N];\n" + "\t\tint first,last,cursize;\n" + "\n" + "\t\tvoid increment(int& x)\n" + "\t\t{\n" + "\t\t\tif ( ++x >= N )\n" + "\t\t\t{\n" + "\t\t\t\tx = 0;\n" + "\t\t\t}\n" + "\t\t}\n" + "\t};\n" + "\n" + ); + + // event queue instance + fprintf(f, + "\t// event queue\n" + "\tStaticQueue ___HSM_EVENT_QUEUE___;\n" + "\n", + m.GetQueueSize() + ); + + // debug string pointer + fprintf(f, + "\t// debug string pointer\n" + "\tchar* ___HSM_DEBUG_MSG___;\n" + "\n" + ); + + // our data + fprintf(f, + "\t// current state\n" + "\tint ___HSM_CURSTATE___;\n" + "\n" + ); + + // private events + fprintf(f, + "\t// private events\n" + ); + OutputPrivateEvents(f,m); + + // a few other #defines + fprintf(f, + "\t// special private constants\n" + "\tenum\n" + "\t{\n" + "\t\t___HSM_NULL_STATE___ = -1,\n" + "\t\t___HSM_TERMINAL_STATE___ = -2,\n" + "\t\t___HSM_ERROR___ = -3,\n" + "\t\t___HSM_MAX_DEPTH___ = %d,\n" + "\t\t___HSM_TIMER_DEPTH___ = %d\n" + "\t};\n" + "\n", + m.GetMaxDepth(), + m.GetTimerDepth() + ); + + // timer declaration + if ( m.GetTimerDepth() > 0 ) + { + fprintf(f, + "\t// timers\n" + "\tfloat ___HSM_TIMERS___[___HSM_TIMER_DEPTH___];\n" + "\n" + ); + } + + // state prototypes + fprintf(f, + "\t// state declaration\n" + ); + OutputStateProtos(f,m,0); // <-- recursive + fprintf(f,"\n"); + + // state table declaration + fprintf(f, + "\t// state table declaration\n" + "\ttypedef int (%s::*___HSMSTATE_FUNC___)(int);\n" + "\tstatic ___HSMSTATE_FUNC___ ___HSM_STATE_TAB___[___HSM_NUM_STATES___];\n" + "\n", + m.name.c_str() + ); + + // machine driver prototypes + fprintf(f, + "\t// machine driver prototypes\n" + "\tvoid ___HSM_START_MACHINE___();\n" + "\tvoid ___HSM_STOP_MACHINE___();\n" + "\tvoid ___HSM_CALC_HIERARCHY___(int state, int path[___HSM_MAX_DEPTH___]);\n" + "\tvoid ___HSM_TRANSITION___(int state);\n" + "\tint ___HSM_CALL_STATE___(int state, int event);\n" + "\tvoid ___HSM_HANDLE_EVENT___(int event);\n" + "\tvoid ___HSM_UPDATE_TIMERS___(float dt);\n" + "\tvoid ___HSM_START_TIMER___(int id, float time);\n" + "\tvoid ___HSM_STOP_TIMER___(int id);\n" + "\tvoid ___HSM_DEBUG___(char* msg);\n" + "\n" + ); + + // footer + fprintf(f, + "};\n" + "\n" + "#endif // ___HSMC_GENERATED_%s___\n" + "\n", + m.name.c_str() + ); + +} + +void OutputMachineHSMDebug(FILE* f, Machine& m) +{ + fprintf(f, + "//\n" + "// debug hook (override this to trap debug messages)\n" + "//\n" + ); + + fprintf(f, + "void %s::HSMDebug(char* msg)\n" + "{\n" + "\t// empty\n" + "}\n" + "\n", + m.name.c_str() + ); +} + +void OutputMachineDriverCode(FILE* f, Machine& m) +{ + fprintf(f, + "%s::%s()\n" + "{\n" + "\t___HSM_CURSTATE___ = ___HSM_NULL_STATE___;\n" + "\t___HSM_DEBUG_MSG___ = \"\";\n" + "}\n" + "\n" + "%s::~%s()\n" + "{\n" + "\tif ( ___HSM_CURSTATE___ != ___HSM_NULL_STATE___ )\n" + "\t{\n" + "\t\t#if _DEBUG\n" + "\t\t\tprintf(\"\\n\\nHSM SHOULD BE EXITED via HSMDestruct() BEFORE DESTRUCTION!!!\\n\\n\\n\");\n" + "\t\t\twhile(1); // infinite loop\n" + "\t\t#else // _DEBUG\n" + "\t\t\tHSMDestruct();\n" + "\t\t#endif // _DEBUG\n" + "\t}\n" + "}\n" + "\n" + "int %s::HSMGetCurrentState() const\n" + "{\n" + "\treturn ___HSM_CURSTATE___;\n" + "}\n" + "\n" + "int %s::HSMGetParentState(int state) const\n" + "{\n" + "\t// valid state?\n" + "\tif ( state >= 0 && state < ___HSM_NUM_STATES___ )\n" + "\t{\n" + "\t\t// const_cast used here because we know that pinging a state with ___HSM_ELICIT_PARENT___ is const-safe\n" + "\t\treturn const_cast<%s*>(this)->___HSM_CALL_STATE___(state,___HSM_ELICIT_PARENT___);\n" + "\t}\n" + "\n" + "\treturn ___HSM_NULL_STATE___;\n" + "}\n" + "\n" + "bool %s::HSMIsInState(int state) const\n" + "{\n" + "\tint parent = ___HSM_CURSTATE___;\n" + "\n" + "\t// valid state?\n" + "\tif ( state >= 0 && state < ___HSM_NUM_STATES___ )\n" + "\t{\n" + "\t\tdo\n" + "\t\t{\n" + "\t\t\tif ( state == parent )\n" + "\t\t\t{\n" + "\t\t\t\treturn true;\n" + "\t\t\t}\n" + "\t\t}\n" + "\t\twhile ( (parent = HSMGetParentState(parent)) >= 0 );\n" + "\t}\n" + "\n" + "\treturn false;\n" + "}\n" + "\n" + "bool %s::HSMIsRunning() const\n" + "{\n" + "\tint s = HSMGetCurrentState();\n" + "\treturn (s >= 0 && s < ___HSM_NUM_STATES___);\n" + "}\n" + "\n" + "void %s::HSMConstruct()\n" + "{\n" + "\t___HSM_START_MACHINE___();\n" + "}\n" + "\n" + "void %s::HSMDestruct()\n" + "{\n" + "\t___HSM_STOP_MACHINE___();\n" + "}\n" + "\n" + "bool %s::HSMUpdate(float dt)\n" + "{\n" + "\t\t// TODO - update timers, trigger events as necessary\n" + "\tif ( HSMIsRunning() )\n" + "\t{\n" + "\t\t// update timers\n" + "\t\t___HSM_UPDATE_TIMERS___(dt);\n" + "\n" + "\t\t// process all current events\n" + "\t\tunsigned int numevents = ___HSM_EVENT_QUEUE___.size();\n" + "\t\tfor (unsigned int i=0;i 0;i++)\n" + "\t\t{\n" + "\t\t\tint e = -1;\n" + "\t\t\tif ( ___HSM_EVENT_QUEUE___.get(e) )\n" + "\t\t\t{\n" + "\t\t\t\t___HSM_HANDLE_EVENT___(e);\n" + "\t\t\t}\n" + "\t\t}\n" + "\n" + "\t\t// now handle our idle event (for the call to Update())\n" + "\t\t___HSM_HANDLE_EVENT___(___HSM_IDLE___);\n" + "\t}\n" + "\n" + "\t// return if we're still running\n" + "\treturn HSMIsRunning();\n" + "}\n" + "\n" + "void %s::HSMTrigger(int event)\n" + "{\n" + "\tif ( event >= 0 && event < ___HSM_NUM_EVENTS___ )\n" + "\t{\n" + "\t\tif ( !___HSM_EVENT_QUEUE___.put(event) )\n" + "\t\t{\n" + "\t\t\t___HSM_DEBUG___(\"Event queue overflow!!!\");\n" + "\t\t}\n" + "\t}\n" + "}\n" + "\n" + "char* %s::HSMGetLastDebugMessage()\n" + "{\n" + "\treturn ___HSM_DEBUG_MSG___;\n" + "}\n" + "\n" + "void %s::___HSM_HANDLE_EVENT___(int event)\n" + "{\n" + "\tif ( event >= 0 && event < ___HSM_TOTAL_NUM_EVENTS___ )\n" + "\t{\n" + "\t\tint s = ___HSM_CURSTATE___;\n" + "\t\twhile ( s >= 0 && s < ___HSM_NUM_STATES___ )\n" + "\t\t{\n" + "\t\t\ts = ___HSM_CALL_STATE___(s,event);\n" + "\t\t}\n" + "\t}\n" + "}\n" + "\n" + "void %s::___HSM_START_MACHINE___()\n" + "{\n" + "\tif ( ___HSM_CURSTATE___ == ___HSM_NULL_STATE___ )\n" + "\t{\n" + "\t\t// empty event queue\n" + "\t\t___HSM_EVENT_QUEUE___.clear();\n" + "\n" + "\t\t// reset any timers\n" + "\t\tfor (int i=0;i<___HSM_TIMER_DEPTH___;i++)\n" + "\t\t{\n" + "\t\t\t___HSM_STOP_TIMER___(i);\n" + "\t\t}\n" + "\n" + "\t\t// go to first state\n" + "\t\t___HSM_TRANSITION___(TOPSTATE);\n" + "\t}\n" + "}\n" + "\n" + "void %s::___HSM_STOP_MACHINE___()\n" + "{\n" + "\tif ( ___HSM_CURSTATE___ != ___HSM_NULL_STATE___ )\n" + "\t{\n" + "\t\t// exit all states to the root\n" + "\t\twhile ( ___HSM_CURSTATE___ != TOPSTATE )\n" + "\t\t{\n" + "\t\t\t___HSM_CALL_STATE___(___HSM_CURSTATE___,___HSM_EXIT___);\n" + "\t\t\t___HSM_CURSTATE___ = ___HSM_CALL_STATE___(___HSM_CURSTATE___,___HSM_ELICIT_PARENT___);\n" + "\t\t}\n" + "\n" + "\t\t// and finally exit the root state\n" + "\t\t___HSM_CALL_STATE___(TOPSTATE,___HSM_EXIT___);\n" + "\t\t___HSM_CURSTATE___ = ___HSM_NULL_STATE___;\n" + "\t}\n" + "}\n" + "\n" + "int %s::___HSM_CALL_STATE___(int state, int event)\n" + "{\n" + "\tif ( state < 0 || state >= ___HSM_NUM_STATES___ )\n" + "\t{\n" + "\t\t// invalid state id\n" + "\t\treturn ___HSM_ERROR___;\n" + "\t}\n" + "\telse\n" + "\t{\n" + "\t\t// valid state, lookup state function in table and call it\n" + "\t\treturn ((*this).*(___HSM_STATE_TAB___[state])) (event);\n" + "\t}\n" + "}\n" + "\n" + "void %s::___HSM_CALC_HIERARCHY___(int state, int path[___HSM_MAX_DEPTH___])\n" + "{\n" + "\tint num = 0;\n" + "\tint parent;\n" + "\n" + "\t// valid state?\n" + "\tif ( state >= 0 && state < ___HSM_NUM_STATES___ )\n" + "\t{\n" + "\t\t// add self\n" + "\t\tpath[num++] = state;\n" + "\n" + "\t\t// add parents\n" + "\t\tparent = state;\n" + "\t\twhile ( (parent = ___HSM_CALL_STATE___(parent,___HSM_ELICIT_PARENT___)) >= 0 )\n" + "\t\t{\n" + "\t\t\tpath[num++] = parent;\n" + "\t\t}\n" + "\t}\n" + "\n" + "\t// set remainder to NULL\n" + "\tfor (int i=num;i<___HSM_MAX_DEPTH___;i++)\n" + "\t{\n" + "\t\t// note that an invalid state comes straight here\n" + "\t\tpath[i] = ___HSM_NULL_STATE___;\n" + "\t}\n" + "}\n" + "\n" + "void %s::___HSM_TRANSITION___(int state)\n" + "{\n" + "\twhile ( state >= 0 && state < ___HSM_NUM_STATES___ )\n" + "\t{\n" + "\t\t// determine path to root for each state\n" + "\t\tint ExitPath[___HSM_MAX_DEPTH___];\n" + "\t\tint EntryPath[___HSM_MAX_DEPTH___];\n" + "\t\t___HSM_CALC_HIERARCHY___(___HSM_CURSTATE___,ExitPath);\n" + "\t\t___HSM_CALC_HIERARCHY___(state,EntryPath);\n" + "\n" + "\t\t//\n" + "\t\t// discover LCA\n" + "\t\t//\n" + "\t\tint ientry = ___HSM_MAX_DEPTH___ - 1;\n" + "\t\tint iexit = ___HSM_MAX_DEPTH___ - 1;\n" + "\n" + "\t\t// find root state in each path (or -1)\n" + "\t\twhile ( ientry >= 0 && EntryPath[ientry] == ___HSM_NULL_STATE___ )\n" + "\t\t{\n" + "\t\t\tientry--;\n" + "\t\t}\n" + "\t\twhile ( iexit >= 0 && ExitPath[iexit] == ___HSM_NULL_STATE___ )\n" + "\t\t{\n" + "\t\t\tiexit--;\n" + "\t\t}\n" + "\n" + "\t\t// beginning at root states, walk backwards until we find the LCA\n" + "\t\twhile ( ientry >= 0 && iexit >= 0 && EntryPath[ientry] == ExitPath[iexit] )\n" + "\t\t{\n" + "\t\t\tientry--;\n" + "\t\t\tiexit--;\n" + "\t\t}\n" + "\n" + "\t\t// deal with self transition\n" + "\t\tif ( ___HSM_CURSTATE___ == state && ientry == -1 && iexit == -1 )\n" + "\t\t{\n" + "\t\t\tientry++;\n" + "\t\t\tiexit++;\n" + "\t\t}\n" + "\n" + "\t\t//\n" + "\t\t// walk transition\n" + "\t\t//\n" + "\n" + "\t\t// call exit routines\n" + "\t\tfor ( int i=0;i<=iexit;i++ )\n" + "\t\t{\n" + "\t\t\t___HSM_CALL_STATE___(ExitPath[i],___HSM_EXIT___);\n" + "\t\t}\n" + "\n" + "\t\t// call entry routines\n" + "\t\tfor ( int i=ientry;i>=0;i-- )\n" + "\t\t{\n" + "\t\t\t___HSM_CALL_STATE___(EntryPath[i],___HSM_ENTRY___);\n" + "\t\t}\n" + "\n" + "\t\t// set current state\n" + "\t\t___HSM_CURSTATE___ = state;\n" + "\n" + "\t\t// now check state for Default transitions\n" + "\t\tstate = ___HSM_CALL_STATE___(___HSM_CURSTATE___,___HSM_ELICIT_INITIAL_TRANSITION___);\n" + "\t}\n" + "}\n" + "\n" + "void %s::___HSM_DEBUG___(char* msg)\n" + "{\n" + "\t___HSM_DEBUG_MSG___ = msg;\n" + "\tHSMDebug(msg);\n" + "}\n" + "\n", + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str(), + m.name.c_str() + ); + + // timer functions + if ( m.GetTimerDepth() > 0 ) + { + fprintf(f, + "void %s::___HSM_UPDATE_TIMERS___(float dt)\n" + "{\n" + "\tfor (int i=0;i<___HSM_TIMER_DEPTH___;i++)\n" + "\t{\n" + "\t\tif ( ___HSM_TIMERS___[i] >= 0.0f )\n" + "\t\t{\n" + "\t\t\t___HSM_TIMERS___[i] -= dt;\n" + "\t\t\tif ( ___HSM_TIMERS___[i] < 0.0f )\n" + "\t\t\t{\n" + "\t\t\t\tif ( !___HSM_EVENT_QUEUE___.put(___HSM_TIMER_0___+i) )\n" + "\t\t\t\t{\n" + "\t\t\t\t\t___HSM_DEBUG___(\"Event queue overflow!!!\");\n" + "\t\t\t\t}\n" + "\t\t\t}\n" + "\t\t}\n" + "\t}\n" + "}\n" + "\n" + "void %s::___HSM_START_TIMER___(int id, float time)\n" + "{\n" + "\t___HSM_TIMERS___[id] = time;\n" + "}\n" + "\n" + "void %s::___HSM_STOP_TIMER___(int id)\n" + "{\n" + "\t___HSM_TIMERS___[id] = -1.0f;\n" + "}\n" + "\n", + m.name.c_str(), + m.name.c_str(), + m.name.c_str() + ); + } + else + { + fprintf(f, + "void %s::___HSM_UPDATE_TIMERS___(float dt)\n" + "{ // no timers in this machine\n" + "}\n" + "\n" + "void %s::___HSM_START_TIMER___(int id, float time)\n" + "{ // no timers in this machine\n" + "}\n" + "\n" + "void %s::___HSM_STOP_TIMER___(int id)\n" + "{ // no timers in this machine\n" + "}\n" + "\n", + m.name.c_str(), + m.name.c_str(), + m.name.c_str() + ); + } +} + +void OutputMachineCPP(FILE* f, std::string incfile, Machine& m){ + // a warning + OutputNotice(f); + + fprintf(f, + "#include \"%s\"\n" + "#if _DEBUG\n" + "#\tinclude \n" + "#endif // _DEBUG\n" + "\n", + incfile.c_str() + ); + + // actions + OutputActions(f,m); + + // HSMDebug() overrideable + OutputMachineHSMDebug(f,m); + + // state table + OutputStateTable(f,m); + + // driver code + OutputMachineDriverCode(f,m); + + // now states + OutputStates(f,m); +} + + + +// +// main program +// + +int main(int argc, char *argv[]) +{ + // parse command line + if ( !gConfig.ParseCommandLine(argc,argv) ) + { + return 1; + } + + // header + if ( !gConfig.Quiet ) + { + printf("Compiling '%s'...\n",gConfig.InFileName.c_str()); + } + + // open input file + AutoFILE infile((char*)gConfig.InFileName.c_str(),"r"); + if ( !infile.Opened() ) + { + printf("ERROR: unable to open '%s'\n",gConfig.InFileName.c_str()); + return 1; + } + + // parse input file + yyin = infile; + if ( yyparse() != 0 ) + { + printf("ERROR: parser failed\n"); + return 1; + } + + // bail if we had errors during parse or validation [done at EndMachine()] + if ( gErrors > 0 ) + { + printf("\nERROR: compilation aborted due to errors\n"); + return 1; + } + + // input looks OK! + if ( !gConfig.Quiet ) + { + printf("Writing '%s', '%s'...\n",gConfig.OutCPPFileName.c_str(),gConfig.OutHFileName.c_str()); + } + + // open output files + AutoFILE cppout((char*)gConfig.OutCPPFileName.c_str(),"w"); + if ( !cppout.Opened() ) + { + printf("ERROR: unable to open '%s'\n",gConfig.OutCPPFileName.c_str()); + return 1; + } + AutoFILE hout((char*)gConfig.OutHFileName.c_str(),"w"); + if ( !hout.Opened() ) + { + printf("ERROR: unable to open '%s'\n",gConfig.OutHFileName.c_str()); + return 1; + } + + // output code + for ( std::vector::iterator it = gMachines.begin(); it != gMachines.end(); it++ ) + { + OutputMachineH( hout, *it ); + OutputMachineCPP( cppout, gConfig.IncludeName, *it ); + } + + // done + if ( !gConfig.Quiet ) + { + printf("done.\n"); + } + return 0; +} + diff --git a/source/main.h b/source/main.h new file mode 100644 index 0000000..20fd1a4 --- /dev/null +++ b/source/main.h @@ -0,0 +1,29 @@ +#ifndef __main_h__ +#define __main_h__ + +#if defined(__cplusplus) +extern "C" { +#endif // defined(__cplusplus) + + void parseEndMachine(); + void parseEndState(); + void parseBeginMachine(char* name,int eventsize); + void parseBeginState(char* name); + void parseDefault(char* state); + void parseEntry(char* action); + void parseIdle(char* action); + void parseExit(char* action); + void parseTransition(char* event,char* state); + void parseAction(char* event,char* action); + void parseTimeTransition(float time,char* state); + void parseTimeAction(float time,char* action); + void parseTerminate(char* event); + + int yyparse(); + +#if defined(__cplusplus) +} +#endif // defined(__cplusplus) + +#endif // __main_h__ + diff --git a/source/state.h b/source/state.h new file mode 100644 index 0000000..09c4baf --- /dev/null +++ b/source/state.h @@ -0,0 +1,33 @@ +#ifndef __state_h__ +#define __state_h__ + +#include +#include +#include + +class State +{ +public: + + std::string name; + + int parent; + std::vector child; + + std::string defaultstate; + std::vector entry; + std::vector idle; + std::vector exit; + std::map transition; + std::multimap action; + std::set terminate; + std::multimap timetransition; + std::multimap timeaction; + + std::map timers; +}; + + +#endif // __state_h__ + +