diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dlc/sm2c/fsmfront.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/dlc/sm2c/fsmfront.c')
-rw-r--r-- | private/ntos/dlc/sm2c/fsmfront.c | 512 |
1 files changed, 512 insertions, 0 deletions
diff --git a/private/ntos/dlc/sm2c/fsmfront.c b/private/ntos/dlc/sm2c/fsmfront.c new file mode 100644 index 000000000..2e89e60d5 --- /dev/null +++ b/private/ntos/dlc/sm2c/fsmfront.c @@ -0,0 +1,512 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation +Copyright (c) 1991 Nokia Data Systems AB + +Module Name: + + fsmfront.c + +Abstract: + + The front end of FSM2C (Finite State Machine to C) compiler. + Reads the FSM definition file to the internal data structures. + +Author: + + Antti Saarenheimo [o-anttis] 07-MAY-1991 + +Revision History: + + 21-MAY-1991 (ASa): + Support for multiple state definitions for one transition (as + used in 802.2 state machine specification). +--*/ + +#include <fsm.h> + +typedef enum { + FSM_TOKEN_DEFINE, + FSM_TOKEN_CONSTANTS, + FSM_TOKEN_STATES_DEF, + FSM_TOKEN_STATE_DEF, + FSM_TOKEN_SYNONYMES, + FSM_TOKEN_INPUTS_DEF, + FSM_TOKEN_INPUT, + FSM_TOKEN_VARIABLES, + FSM_TOKEN_STATE, + FSM_TOKEN_NAME, + FSM_TOKEN_TRANSIT, + FSM_TOKEN_CONDITION, + FSM_TOKEN_ACTION, + FSM_TOKEN_NEW_STATE, + FSM_TOKEN_SPEED, + FSM_TOKEN_UNKNOWN_KEY, + FSM_TOKEN_COMMENT, + FSM_TOKEN_INVALID_LINE, + FSM_TOKEN_END_OF_FILE, + FSM_NO_STATE} +FSM_TOKENS; + +// internal functions +VOID TokenizeFsmDef( + FILE *fd, // stdio stream handle + PUSHORT pusToken, // Token ID + UCHAR auchToken[], // token string (needed when the key is variable) + PUSHORT pcbToken, // size of the token string + UCHAR auchData[], // data buffer + PUSHORT pcbData, // size of the data buffer + PUSHORT pusLine // current link number + ); +INT RemoveChars( PSZ pszStr, PSZ pszRemoved ); +VOID ReadDefinitions( + PVOID hHash, PSZ pszInput, USHORT usLine, + PUSHORT pusEnum, PUSHORT pusCount, PBOOL pboolErrorFound, + PFSM_TOKEN FAR * ppDef); + +// +// FsmInitTables +// +VOID FsmInitTables( ) +{ + // + hDefines = StrHashNew( 200 ); + hVariables = StrHashNew( 200 ); + hSynonymes = StrHashNew( 200 ); + hStates = StrHashNew( 200 ); + hInputs = StrHashNew( 200 ); + hConditions = StrHashNew( 200 ); + + // allocate the state and input definition tables + ppStateDefs = (PVOID FAR *)Alloc( 512 * sizeof( PVOID )); + ppInputDefs = (PVOID FAR *)Alloc( 1024 * sizeof( PVOID )); +} + +// +// This state machine reads the FSM definition file to the +// data structures and does the initial syntax checking for +// the expressions. +// +// Input: +// The file handle of FSM definiton file. +// Output, the global data structures: +// +// +PFSM_TRANSIT FsmFront( FILE *fd, PFSM_TRANSIT pBase ) +{ + USHORT usMainState = FSM_NO_STATE; + USHORT usSubState; + USHORT usLine = 1, cbToken, cbData; + USHORT usToken; + USHORT usStateEnum = 0, usInputEnum = 0; + PFSM_STR_REDEF pDef; + PFSM_TOKEN pStr; + PFSM_TRANSIT pTransit = NULL; + PVOID hCurrent; + PSZ pszCurState = NULL; + BOOL boolErrorFound = FALSE; + static PSZ pszToken = 0, pszData = 0; + + if (pszToken == 0) + pszToken = Alloc( MAX_LINE_LEN ); + if (pszData == 0) + pszData = Alloc( MAX_LINE_LEN ); + + // read the definitons + for (;;) + { + TokenizeFsmDef( + fd, &usToken, pszToken, &cbToken, pszData, &cbData, &usLine); + + // handle the main state transitions (they can be anywhere!) + if (usToken == FSM_TOKEN_STATE) + { + usSubState = usMainState = usToken; + break; + } + else if (usToken == FSM_TOKEN_DEFINE) + { + usMainState = usToken; + } + else if (usToken == FSM_TOKEN_END_OF_FILE) + { + // end of this loop + break; + } + else if (usMainState == FSM_TOKEN_DEFINE) + { + if (usToken == FSM_TOKEN_CONSTANTS || + usToken == FSM_TOKEN_SYNONYMES || + usToken == FSM_TOKEN_VARIABLES || + usToken == FSM_TOKEN_STATES_DEF) + { + usSubState = usToken; + } + else if (usToken == FSM_TOKEN_NAME) + { + pszFsmName = StrAlloc( pszData ); + } + else + { + // reding the definitions + switch (usSubState) + { + case FSM_TOKEN_CONSTANTS: + hCurrent = hDefines; + break; + case FSM_TOKEN_SYNONYMES: + hCurrent = hSynonymes; + break; + case FSM_TOKEN_STATES_DEF: + if (usToken == FSM_TOKEN_INPUT) + { + ReadDefinitions( + hInputs, pszData, usLine, + &usInputEnum, &cInputs, &boolErrorFound, + ppInputDefs ); + } + else if (usToken == FSM_TOKEN_STATE_DEF) + { + ReadDefinitions( + hStates, pszData, usLine, + &usStateEnum, &cStates, &boolErrorFound, + ppStateDefs ); + } + else + { + PrintErrMsg( + usLine, FSM_ERROR_INVALID_LINE, pszToken ); + boolErrorFound = TRUE; + } + break; + case FSM_TOKEN_VARIABLES: + hCurrent = hVariables; + break; + } + if (usSubState != FSM_TOKEN_STATES_DEF) + { + if (usToken != FSM_TOKEN_UNKNOWN_KEY || cbData == 0) + { + PrintErrMsg( usLine, FSM_ERROR_INVALID_LINE, pszToken ); + } + else + { + // read the definition + if (HashSearch( hCurrent, &pszToken ) != NULL) + { + PrintErrMsg( + usLine, FSM_ERROR_ALREADY_EXIST, pszToken ); + } + else + { + NEW( pDef ); + pDef->pszOrginal = StrAlloc( pszToken ); + pDef->pszReplace = StrAlloc( pszData ); + HashAdd( hCurrent, pDef); + } + } + } + } + } + else if (usMainState == FSM_NO_STATE || + usToken == FSM_TOKEN_INVALID_LINE) + { + // we start from here + boolErrorFound = TRUE; + PrintErrMsg( usLine, FSM_ERROR_INVALID_LINE, pszToken ); + } + } + // read the actions and state transitions + for (;;) + { + TokenizeFsmDef( + fd, &usToken, pszToken, &cbToken, pszData, &cbData, &usLine); + + if (usToken == FSM_TOKEN_END_OF_FILE) + { + // end of this loop + break; + } + else if (usToken == FSM_TOKEN_STATE) + { + usSubState = usToken; + pszCurState = NULL; + } + else if (usToken == FSM_TOKEN_TRANSIT) + { + if (pszCurState == NULL) + { + boolErrorFound = TRUE; + PrintErrMsg( usLine, FSM_ERROR_STATE_NOT_DEFINED, pszToken ); + } + usSubState = usToken; + + // check the previous state transition, the input and + // action fields must be non empty + if (pTransit != NULL && + (pTransit->pszAction == NULL || pTransit->pszInput == NULL || + !*pTransit->pszAction || !*pTransit->pszInput)) + { + boolErrorFound = TRUE; + PrintErrMsg( + pTransit->usLine, FSM_ERROR_MISSING_FIELD, NULL ); + } + // add the transition to a linked list + NEW( pTransit ); + pBase = LinkElement( pBase, pTransit ); + pTransit->usLine = usLine; + pTransit->usNewState = -1; + pTransit->pszCurState = pszCurState; + } + else if (usSubState == FSM_TOKEN_STATE) + { + if (usToken == FSM_TOKEN_NAME) + { + pszCurState = StrAlloc( pszData ); + } + else + { + // error !!! + boolErrorFound = TRUE; + PrintErrMsg( usLine, FSM_ERROR_INVALID_LINE, pszToken ); + } + } + else if (usSubState == FSM_TOKEN_TRANSIT && cbData > 0) + { + switch (usToken) + { + case FSM_TOKEN_INPUT: + pTransit->pszInput = StrAlloc( pszData ); + break; + case FSM_TOKEN_CONDITION: + pTransit->pszCondition = StrAlloc( pszData ); + break; + case FSM_TOKEN_ACTION: + pTransit->pszAction = StrAlloc( pszData ); + break; + case FSM_TOKEN_NEW_STATE: + if (cbData != 0) + { + if ((pStr = HashSearch( hStates, &pszData )) != NULL) + pTransit->usNewState = pStr->usToken; + else + { + boolErrorFound = TRUE; + PrintErrMsg( + usLine, FSM_ERROR_INVALID_LINE, pszData ); + } + } + break; + case FSM_TOKEN_SPEED: + if (cbData != 0) + { + pTransit->usSpeed = atoi( pszData ); + } + break; + default: + // error !!! + boolErrorFound = TRUE; + PrintErrMsg( usLine, FSM_ERROR_INVALID_LINE, pszToken ); + break; + } + } + } + if (boolErrorFound) + return NULL; + else + return pBase; +} +// +// Tokens bound to strings +// +FSM_TOKEN aFsmKeys[] = { + {"[[Define]]", FSM_TOKEN_DEFINE}, + {"[Constants]", FSM_TOKEN_CONSTANTS}, + {"[StateInputs]", FSM_TOKEN_STATES_DEF}, + {"State", FSM_TOKEN_STATE_DEF}, +// {"[Inputs]", FSM_TOKEN_INPUTS_DEF}, + {"Input", FSM_TOKEN_INPUT}, + {"[Variables]", FSM_TOKEN_VARIABLES}, + {"[Synonymes]", FSM_TOKEN_SYNONYMES}, + {"[[State]]", FSM_TOKEN_STATE}, + {"Name", FSM_TOKEN_NAME}, + {"[Transition]", FSM_TOKEN_TRANSIT}, + {"Predicate", FSM_TOKEN_CONDITION}, + {"Action", FSM_TOKEN_ACTION}, + {"NewState", FSM_TOKEN_NEW_STATE}, + {"Speed", FSM_TOKEN_SPEED}, + { NULL, FSM_TOKEN_UNKNOWN_KEY}}; + +#define MAX_FSM_C_LINE MAX_LINE_LEN * 20 +// +// Procedure reads the next (semantic) line from the FSM definition file. +// The lines having '\' in the last character will be catenated to the +// next on (just as in C) +// +VOID TokenizeFsmDef( + FILE *fd, // stdio stream handle + PUSHORT pusToken, // Token ID + PSZ pszToken, // token string (needed when the key is variable) + PUSHORT pcbToken, // size of the token string + PSZ pszData, // data buffer + PUSHORT pcbData, // size of the data buffer + PUSHORT pusLine // current link number + ) +{ + static UCHAR auchLine[ MAX_FSM_C_LINE ]; + USHORT i, cbData; + + for (;;) + { + if (fgets(auchLine, MAX_LINE_LEN - 1, fd ) == NULL) + { + *pusToken = FSM_TOKEN_END_OF_FILE; + break; + } + (*pusLine)++; + + // remove all tabulators, spaces, newlines, carrige returns from + // the read line (makes the handling much simpler + RemoveChars( auchLine, " \t\n\r"); + + ReadExpression( + auchLine, pszToken, pcbToken, pszData, pcbData, "=", ""); + + // skip all empty files and comments + if (!*pszToken || *pszToken == ';') + continue; + + // search the token + for (i = 0; aFsmKeys[i].pszToken != NULL; i++) + if (!_stricmp( aFsmKeys[i].pszToken, pszToken )) + break; + *pusToken = aFsmKeys[i].usToken; + + // catenate all lines together having a backslash in the end + cbData = *pcbData; + while (pszData[--cbData] == '\\' && + cbData < MAX_FSM_C_LINE - MAX_LINE_LEN) + { + if (fgets(pszData + cbData, MAX_LINE_LEN - 1, fd) != NULL) + { + (*pusLine)++; + RemoveChars( pszData + cbData, " \t\n\r"); + *pcbData = cbData = strlen( pszData ); + } + else + { + *pusToken = FSM_TOKEN_END_OF_FILE; + break; + } + } + break; + } +} + +// +// Procedure removes all characters in the second string from the first one. +// +INT RemoveChars( PSZ pszStr, PSZ pszRemoved ) +{ + USHORT cbRemoved = strlen( pszRemoved ); + USHORT iSrc, iDest; + + for (iSrc = iDest = 0; pszStr[iSrc]; iSrc++, iDest++) + { + while (memchr(pszRemoved, pszStr[iSrc], cbRemoved)) iSrc++; + pszStr[iDest] = pszStr[iSrc]; + } + return iDest - 1; +} + +// +// Reads two strings separated by a set of separators and terminated +// by terminators. Returs the length of the read bytes. Skips over all +// terminators in the end of the string. +// +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 + ) +{ + USHORT i; + BOOL boolSeparsFound = FALSE; + USHORT cbSepars = strlen( pszSepars ); + USHORT iDest1 = 0, iDest2 = 0; + USHORT cbTermins = strlen( pszTermins ); + + for (i = 0; pszSrc[i]; i++) + { + if (!boolSeparsFound && memchr(pszSepars, pszSrc[i], cbSepars)) + { + boolSeparsFound = TRUE; + } + else + { + if (memchr(pszTermins, pszSrc[i], cbTermins)) + break; + if (boolSeparsFound) + pszDest2[iDest2++] = pszSrc[i]; + else + pszDest1[iDest1++] = pszSrc[i]; + } + } + pszDest1[iDest1] = 0; + if (boolSeparsFound) + pszDest2[iDest2] = 0; + + // skip over all termination characters in the end of read data + while (pszSrc[i] && memchr(pszTermins, pszSrc[++i], cbTermins) != NULL); + *pusDest1 = iDest1; + *pusDest2 = iDest2; + return i; +} + +// +// Procedure reads an input and state defintion lile. +// The format of the line is similar to C- enumeration: +// The states and inputs can be set values +// +VOID ReadDefinitions( + PVOID hHash, PSZ pszInput, USHORT usLine, + PUSHORT pusEnum, PUSHORT pusCount, PBOOL pboolErrorFound, + PFSM_TOKEN FAR * ppDefTbl) +{ + UCHAR auchBuf1[MAX_LINE_LEN]; // max input string length + UCHAR auchBuf2[MAX_LINE_LEN]; // max input string length + PSZ pszToken = (PSZ)auchBuf1; + PSZ pszData = (PSZ)auchBuf2; + USHORT cbToken, cbData; + PFSM_TOKEN pStr; + + do + { + pszInput += + ReadExpression( + pszInput, pszToken, &cbToken, pszData, &cbData, "=", ","); + + // read the definition + if (HashSearch( hHash, &pszToken ) != NULL) + { + PrintErrMsg( + usLine, FSM_ERROR_ALREADY_EXIST, pszData ); + *pboolErrorFound = TRUE; + } + else + { + NEW( pStr ); + pStr->pszToken = StrAlloc( pszToken ); + if (cbData != 0 && isdigit( *pszData )) + (*pusEnum) = atoi( pszData ); + pStr->usEnum = (*pusEnum)++; + ppDefTbl[(*pusCount)] = pStr; + pStr->usToken = (*pusCount)++; + HashAdd( hHash, pStr ); + } + } while( *pszInput ); +} |