/*++ Copyright (c) 1991 Microsoft Corporation Copyright (c) 1991 Nokia Data Systems AB Module Name: fsm.h Abstract: The file includes all internal definition of FSM2C compiler (Finite State Machine to C). Author: Antti Saarenheimo [o-anttis] 06-MAY-1991 Revision History: --*/ //******************* INCLUDES ********************** #include #include #include #include #include #include #include #include //********************* TYPE DEFINITIONS ************************ // // FSM STATE MACHINE DATA STRTCTURES: // ( -> = pointer, <-> = two way link, HDB = hash data base, // This list is not complete, because some links are pointer arrays // within a table, the others are direct pointer links. // The table structures will be usually sorted during compiling, // Some data structures are accessed as a tables in one phase and // linked tree structures in the next one. // The lower objects are shared by the higher level objects and // the objects are joined together whenever it is possible. // Actually that is the main idea of these structure: FSM size // is minimized by these join operations. FSM complexity is also // the main reason for the complexity of these data structures. // // [State][Input] -> TRANSITION // TRANSITION <-> TRANSITION (* HDB *): // -> StateInput -> StateInput (* all input/state pairs using transit) // -> INPUT_ACTIONS (* HBD *): // -> COND_ACTION table (* elemnts are cond/action pairs *) // -> CONDITION (hash DB) // -> INPUT_ACTIONS (* HDB *) // -> ACTION_PRIMITIVE (* table within INPUT_ACTIONS *) // -> ACTION_CODE (* hash db *) // later ACTION_NODES built to a link tree // // Used tools: Link, UnLink for linked lists, qsort, AddToTbl for the // adding and expnading the pointer table objects. // typedef struct _FSM_CONDITION { PSZ pszFsmCode; PSZ pszC_Code; } FSM_CONDITION, FAR *PFSM_CONDITION; typedef struct _FSM_ACT_CODE { PSZ pszFsmCode; PSZ pszC_Code; USHORT cReferCount; } FSM_ACT_CODE, FAR *PFSM_ACT_CODE; typedef struct _FSM_PRIMITIVE { // the root pointers goes to the root of the tree and // leafs poins to list of all leafs of this node (linked by pPeer) struct _FSM_PRIMITIVE FAR *pRoot; // pNext pointer at first struct _FSM_PRIMITIVE FAR *pLeafs; // pPrev at fist struct _FSM_PRIMITIVE FAR *pPeer; // other elemements in the same level PFSM_ACT_CODE pActCode; // pointer to the actual FSM and C code BOOL boolCodeGenerated; // Set true, when the node has the C code USHORT cReferences; // number of refecences to this primitive ULONG usSpeedWeigth; // speed weigth of this node, used in optim. // these are set, when the actual C- code is generated for this primitive, // the primitive has always an own jump address, if it has more than // one leafs. USHORT usCase; // case number pointing to this primitive USHORT usCaseForLabel; // case number used with the label USHORT usLineInCase; // goto label number within the case // eg: case_10_L3: } FSM_PRIMITIVE, FAR *PFSM_PRIMITIVE; typedef struct _FSM_ACTION { struct { PFSM_PRIMITIVE FAR *ppActPrim; USHORT cActPrim; USHORT cMaxActPrim; } dt; } FSM_ACTION, FAR *PFSM_ACTION; typedef struct _COND_ACTION { PFSM_ACTION pAction; PFSM_CONDITION pCond; } COND_ACTION, FAR *PCOND_ACTION; typedef struct _INPUT_ACTIONS { // set NULL when this is the only condition definiton struct _INPUT_ACTIONS FAR * pAlternateConditions; USHORT usCase; // case allocated for this // Keep this sub structure in the beginning (make things easier) struct { PCOND_ACTION FAR * ppCondActions; USHORT cCondActions; // how many now USHORT cMaxCondActions; // max number until realloc } dt; } INPUT_ACTIONS, FAR * PINPUT_ACTIONS; typedef struct _STATE_INPUT { struct _STATE_INPUT FAR *pNext; struct _STATE_INPUT FAR *pPrev; USHORT usState; USHORT usInput; } STATE_INPUT, FAR *PSTATE_INPUT; // this struct is not in the hash table: typedef struct _FSM_TRANSIT { struct _FSM_TRANSIT FAR *pNext; struct _FSM_TRANSIT FAR *pPrev; // This is some stuff for suntax checking used far before // my powerful optimizers have been mixed all data structures PSZ pszCondition; PSZ pszAction; PSZ pszInput; USHORT usSpeed; PSZ pszCurState; USHORT usNewState; USHORT usLine; // This stuff is produced and modified by FsmMerger PSTATE_INPUT pList; USHORT cStateInputs; PINPUT_ACTIONS pInputActions; } FSM_TRANSIT, FAR *PFSM_TRANSIT; typedef struct _LINK_FILE { struct _LINK_FILE FAR * pNext; struct _LINK_FILE FAR * pPrev; USHORT usState; PSZ pszLine; } LINK_FILE, FAR * PLINK_FILE; typedef struct _FSM_TOKEN { PSZ pszToken; // token string USHORT usToken; // # the token USHORT usEnum; // enum value for the token } FSM_TOKEN, FAR *PFSM_TOKEN; typedef struct _FSM_STR_REDEF { PSZ pszOrginal; // The orginal defined string PSZ pszReplace; // its replacement } FSM_STR_REDEF, FAR *PFSM_STR_REDEF; // used to hold on any strings, used only for syntax checking of // states and inputs typedef struct _FSMS_STR { PSZ pszStr; USHORT usToken; } FSMS_STR, FAR *PFSMS_STR; //**************** CONSTANTS ************************ #define NEW( a ) memset((a = Alloc(sizeof(*(a)))), 0, sizeof(*(a))) #define DEL( a ) free(a); a=0 // add also stack size to support longer lines: #define MAX_LINE_LEN 512 enum HashErrors { NO_ERROR = 0, ERROR_HASH_NO_MEMORY, ERROR_HASH_KEY_EXIST, ERROR_HASH_NOT_FOUND}; enum FsmErrors { FSM_NO_ERROR, FSM_ERROR_NEW_STATE_UNDEFINED, FSM_ERROR_UNSYNC_INPUT, FSM_ERROR_UNDEFINED_VARIABLE, FSM_ERROR_ALREADY_EXIST, FSM_ERROR_INVALID_LINE, FSM_ERROR_STATE_NOT_DEFINED, FSM_ERROR_NO_MEMORY, FSM_ERROR_INVALID_EXTENSION, FSM_ERROR_FILE_NOT_FOUND, FSM_ERROR_IN_FILE, FSM_ERROR_MISSING_FIELD, FSM_ERROR_CANNOT_WRITE, FSM_ERROR_MISSING_CONDITION, FSM_ERROR_INPUT_DISCARDED, FSM_ERROR_INPUTS_DO_NOT_MATCH, FSM_ERROR_NO_DEFAULT, FSM_ERROR_OTHER_LINE }; //********************* EXTERNS AND PROTOTYPES ************************ // Hash tables for the different types extern PVOID hDefines; extern PVOID hVariables; extern PVOID hSynonymes; extern PVOID hStates; extern PVOID hInputs; extern PVOID hConditions; extern USHORT cStates; extern USHORT cInputs; extern PVOID FAR * FAR * pppStateInputs; extern PUSHORT pusCondJumpTbl; extern USHORT cCondJumpTbl; extern PFSM_PRIMITIVE pActionTreeBase; extern PUSHORT FAR * ppusStateInputs; extern PFSM_TOKEN FAR * ppInputDefs; extern PFSM_TOKEN FAR * ppStateDefs; extern PSZ pszFsmName; // function prototypes PSZ StrNotBrk( PSZ pszStr, PSZ pszBreaks ); PSZ StrBrk( PSZ pszStr, PSZ pszBreaks ); PFSM_TRANSIT FsmFront( FILE *fd, PFSM_TRANSIT pBase ); PVOID LinkElement( PVOID pBase, PVOID pElement ); PVOID UnLinkElement( PVOID pElement ); PVOID StrHashNew( UINT cElemenst ); PVOID Alloc( UINT cbSize ); PVOID HashNew( UINT cElements, // appr. # elements INT (*Hash)( PVOID pKey ), // returns the hash key INT (*Comp)( PVOID pKey1, PVOID pKey2 ), // Compares the keys PVOID (*Alloc)( UINT cbSize ), // Allocates a memory block VOID (*Free)( PVOID p) // Frees a memory block ); VOID xFree( PVOID p ); INT HashAdd( PVOID hHash, PVOID pData); INT HashUnlink( PVOID hHash, PVOID pData); PVOID HashSearch( PVOID hHash, PVOID pKey ); UINT HashRead( PVOID hHash, // hash handle UINT cElemRead, // # elements to read UINT iFirstElem, // index of the first element PVOID pBuf[] // buffer for the elements ); UINT HashDelete( PVOID hHash ); UINT HashLen( PVOID hHash ); PFSM_TRANSIT FsmBuild( PFSM_TRANSIT pBase ); VOID FsmCodeGeneration( FILE * fd, // the handle of the c- file PLINK_FILE pFile, // file read to a linked list PFSM_TRANSIT pBase, // linked fsm state transitions PSZ pszName // the default body of all names ); PLINK_FILE FsmReadCFile( FILE *fd ); VOID PrintErrMsg( USHORT usLine, USHORT usErr, PSZ pszErr ); VOID AddToTable( PVOID pTbl, PVOID pElement); INT ReadExpression( PSZ pszSrc, // source string PSZ pszDest1, // the first word PUSHORT pusDest1, // its length PSZ pszDest2, // the second word PUSHORT pusDest2, // its length PSZ pszSepars, // the separators PSZ pszTermins // the terminators ); PSZ StrAlloc( PSZ psz ); VOID FsmInitTables( void ); VOID PrintHelpMsg( void ); INT StriCmpFileExt( PSZ pszFile, PSZ pszExt );