/* SCCSWHAT( "@(#)grammar.y 1.4 89/05/09 21:22:03 " ) */ /*****************************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1987-1990 **/ /*****************************************************************************/ %{ /**************************************************************************** *** local defines ***************************************************************************/ #define pascal #define FARDATA #define NEARDATA #define FARCODE #define NEARCODE #define NEARSWAP #define PASCAL pascal #define CDECL #define VOID void #define CONST const #define GLOBAL #define YYSTYPE lextype_t #define YYNEAR NEARCODE #define YYPASCAL PASCAL #define YYPRINT printf #define YYSTATIC static #define YYLEX yylex #define YYPARSER yyparse #define MAXARRAY 1000 #define CASE_BUFFER_SIZE 10000 #define CASE_FN_FORMAT ("\nstatic void\ncase_fn_%.4d()") #define DISPATCH_ENTRY_FORMAT ("\n\t,case_fn_%.4d") #define DISPATCH_FIRST_ENTRY ("\n\t case_fn_%.4d") /**************************************************************************** *** include files ***************************************************************************/ #include #include #include #include #include #include "lex.h" /**************************************************************************** *** externals ***************************************************************************/ extern int Incase; extern int ActionSensed; extern int yylex(); extern int yyparse(); /**************************************************************************** *** local procs ***************************************************************************/ void Init( void ); void EmitCaseTableArray( void ); void EmitDefaultCase( void ); void EmitCaseBody( int ); void RegisterCase( int ); void BufferIt( char * pStr, int iLen ); void ResetBuffer(); void FlushBuffer(); /**************************************************************************** *** local data ***************************************************************************/ unsigned long SavedIDCount = 0; unsigned long IDCount = 0; unsigned char CaseTable[ MAXARRAY ] = { 0 }; int CaseNumber = 0; int MaxCaseNumber = 0; char * pBufStart; char * pBufCur; char * pBufEnd; %} %token ID %token NUMBER %token TOKEN_CASE %token TOKEN_CHAR %token TOKEN_END %token TOKEN_END_CASE %token TOKEN_MYACT %token TOKEN_START %type NUMBER %type TOKEN_CHAR %type ID %% Template: OptionalJunk TOKEN_START { Init(); } OptionalJunk Body OptionalJunk TOKEN_END OptionalJunk { EmitDefaultCase(); EmitCaseTableArray(); } ; Body: TOKEN_MYACT { ActionSensed++; ResetBuffer(); } OptionalJunk CaseList { } ; CaseList: CaseList OneCase { } | OneCase { } ; OneCase: TOKEN_CASE TOKEN_CHAR NUMBER TOKEN_CHAR { Incase = 1; CaseNumber = $3; if($3 >= MAXARRAY) { fprintf(stderr, "Case Limit Reached : Contact Dov/Vibhas\n"); return 1; } SavedIDCount = IDCount; } OptionalJunk TOKEN_END_CASE { if(SavedIDCount != IDCount) { RegisterCase( CaseNumber ); EmitCaseBody( CaseNumber ); } ResetBuffer(); if(CaseNumber > MaxCaseNumber) MaxCaseNumber = CaseNumber; Incase = 0; } ; OptionalJunk: Junk { } | /* Empty */ { } ; Junk: Junk JunkElement { } | JunkElement { } ; JunkElement: TOKEN_CHAR { if(!ActionSensed) fprintf(stdout, "%c", $1); else BufferIt( &$1, 1); } | ID { IDCount++; if(!ActionSensed) fprintf(stdout, "%s", $1); else BufferIt( $1, strlen($1) ); } | NUMBER { if(!ActionSensed) fprintf(stdout, "%d", $1); else { char buffer[20]; sprintf(buffer,"%d", $1 ); BufferIt( buffer, strlen(buffer) ); } } ; %% /***************************************************************************** * utility functions *****************************************************************************/ YYSTATIC VOID FARCODE PASCAL yyerror(char *szError) { extern int Line; extern char LocalBuffer[]; fprintf(stderr, "%s at Line %d near %s\n", szError, Line, LocalBuffer); } void Init() { pBufStart = pBufCur = malloc( CASE_BUFFER_SIZE ); if( !pBufStart ) { fprintf(stderr,"Out Of Memory\n"); exit(1); } pBufEnd = pBufStart + CASE_BUFFER_SIZE; } void BufferIt( char * pStr, int iLen ) { if( pBufCur + iLen > pBufEnd ) { printf("ALERT iLen = %d\n", iLen ); // assert( (pBufCur + iLen) <= pBufEnd ); exit(1); } strncpy( pBufCur , pStr, iLen ); pBufCur += iLen; *pBufCur = '\0'; } void ResetBuffer() { pBufCur = pBufStart; *pBufCur= '\0'; } void FlushBuffer() { fprintf(stdout, "%s", pBufStart); ResetBuffer(); } void EmitCaseBody( int CaseNumber ) { fprintf( stdout, CASE_FN_FORMAT, CaseNumber ); FlushBuffer(); fprintf( stdout, "}\n" ); } void EmitCaseTableArray() { int i, iTemp; fprintf( stdout, "static void\t (*case_fn_array[])() = \n\t{" ); fprintf( stdout,DISPATCH_FIRST_ENTRY, 0 ); for( i = 1 ; i <= MaxCaseNumber ; ++i ) { iTemp = CaseTable[ i ] ? i : 0; fprintf(stdout,DISPATCH_ENTRY_FORMAT, iTemp ); } fprintf( stdout, "\n\t};\n" ); fprintf( stdout, "\nstatic void\nyy_vc_init(){ pcase_fn_array = case_fn_array;\nyym_vc_max = %d;\n }\n" , MaxCaseNumber); } void EmitDefaultCase() { fprintf(stdout, "static void\ncase_fn_%.4d() {\n\t}\n\n", 0 ); } void RegisterCase( int iCase ) { CaseTable[ iCase ] = 1; }