MCLEX.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:11k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1991-1997 Microsoft Corporation
  3. Module Name:
  4.     mclex.c
  5. Abstract:
  6.     This file contains the input lexer for the Win32 Message Compiler (MC)
  7. --*/
  8. #include "mc.h"
  9. char LineBuffer[ 256 ];
  10. char *CurrentChar;
  11. BOOLEAN ReturnCurrentToken;
  12. PNAME_INFO KeywordNames;
  13. typedef struct _COMMENT_INFO {
  14.     struct _COMMENT_INFO *Next;
  15.     char Text[ 1 ];
  16. } COMMENT_INFO, *PCOMMENT_INFO;
  17. PCOMMENT_INFO Comments, CurrentComment;
  18. /*++
  19. Routine Description:
  20.     This fills in the Key words associated with the Message file format
  21. Return Value:
  22.     TRUE
  23. --*/
  24. BOOLEAN
  25. McInitLexer( void )
  26. {
  27.     ReturnCurrentToken = FALSE;
  28.     McAddName( &KeywordNames, "MessageIdTypedef",   MCTOK_MSGIDTYPE_KEYWORD,  NULL );
  29.     McAddName( &KeywordNames, "SeverityNames",      MCTOK_SEVNAMES_KEYWORD,   NULL );
  30.     McAddName( &KeywordNames, "FacilityNames",      MCTOK_FACILITYNAMES_KEYWORD,  NULL );
  31.     McAddName( &KeywordNames, "LanguageNames",      MCTOK_LANGNAMES_KEYWORD,  NULL );
  32.     McAddName( &KeywordNames, "MessageId",          MCTOK_MESSAGEID_KEYWORD,  NULL );
  33.     McAddName( &KeywordNames, "Severity",           MCTOK_SEVERITY_KEYWORD,   NULL );
  34.     McAddName( &KeywordNames, "Facility",           MCTOK_FACILITY_KEYWORD,   NULL );
  35.     McAddName( &KeywordNames, "SymbolicName",       MCTOK_SYMBOLNAME_KEYWORD, NULL );
  36.     McAddName( &KeywordNames, "Language",           MCTOK_LANGUAGE_KEYWORD,   NULL );
  37.     return( TRUE );
  38. }
  39. BOOLEAN
  40. McOpenInputFile( void )
  41. {
  42.     char SavedChar, *s, *FileName;
  43.     BOOLEAN Result;
  44.     s = MessageFileName;
  45.     FileName = s;
  46.     SavedChar = '';
  47.     while (*s) {
  48.         if (*s == '.') {
  49.             SavedChar = '.';
  50.             *s = '';
  51.             break;
  52.             }
  53.         if (*s == ':' || *s == '\' || *s == '/') {
  54.             FileName = s+1;
  55.             }
  56.         s = CharNext(s);
  57. }
  58.     strcat( HeaderFileName, FileName );
  59.     strcat( HeaderFileName, ".h" );
  60.     strcat( RcInclFileName, FileName );
  61.     strcat( RcInclFileName, ".rc" );
  62.     if (SavedChar == '') {
  63.         strcpy( s, ".mc" );
  64.         }
  65.     else {
  66.         *s = SavedChar;
  67.         }
  68.     Result = FALSE;
  69.     MessageFileLineNumber = 0;
  70.     LineBuffer[ 0 ] = '';
  71.     CurrentChar = NULL;
  72.     MessageFile = fopen( MessageFileName, "rb" );
  73.     if (MessageFile == NULL) {
  74.         McInputError( "unable to open input file", TRUE, NULL );
  75.         }
  76.     else {
  77.         HeaderFile = fopen( HeaderFileName, "wb" );
  78.         if (HeaderFile == NULL) {
  79.             McInputError( "unable to open output file - %s", TRUE, HeaderFileName );
  80.             }
  81.         else {
  82.             RcInclFile = fopen( RcInclFileName, "wb" );
  83.             if (RcInclFile == NULL) {
  84.                 McInputError( "unable to open output file - %s", TRUE, RcInclFileName );
  85.                 }
  86.             else {
  87.                 Result = TRUE;
  88.                 }
  89.             }
  90.         }
  91.     if (!Result) {
  92.         McCloseInputFile();
  93.         McCloseOutputFiles();
  94.         }
  95.     else {
  96.         return( TRUE );
  97.         }
  98. }
  99. void
  100. McCloseInputFile( void )
  101. {
  102.     if (MessageFile != NULL) {
  103.         fclose( MessageFile );
  104.         MessageFile = NULL;
  105.         CurrentChar = NULL;
  106.         LineBuffer[ 0 ] = '';
  107.         }
  108. }
  109. void
  110. McCloseOutputFiles( void )
  111. {
  112.     if (HeaderFile != NULL) {
  113.         fclose( HeaderFile );
  114.         }
  115.     if (RcInclFile != NULL) {
  116.         fclose( RcInclFile );
  117.         }
  118. }
  119. void
  120. McInputError(
  121.     char *Message,
  122.     BOOLEAN Error,
  123.     PVOID Argument
  124.     )
  125. {
  126.     fprintf( stderr,
  127.              "%s (%d) : %s: ",
  128.              MessageFileName,
  129.              MessageFileLineNumber,
  130.              Error ? "Error" : "Warning"
  131.            );
  132.     fprintf( stderr, Message, Argument );
  133.     fprintf( stderr, "n" );
  134. }
  135. /*++
  136. Routine Description:
  137.    This retrieves the current line then moves down to the
  138.    next line in the message file.
  139. Return Value:
  140.    Returns the current line of in the file.
  141. --*/
  142. char *
  143. McGetLine( void )
  144. {
  145.     char *s;
  146.     if (MessageFile == NULL || feof( MessageFile )) {
  147.         return( NULL );
  148.         }
  149.     if (fgets( LineBuffer, sizeof( LineBuffer ), MessageFile ) == NULL) {
  150.         return( NULL );
  151.         }
  152.     s = LineBuffer + strlen( LineBuffer );
  153.     if (s > LineBuffer && *--s == 'n') {
  154.         if (s > LineBuffer && *--s != 'r') {
  155.             *++s = 'r';
  156.             *++s = 'n';
  157.             *++s = '';
  158.             }
  159.         }
  160.     MessageFileLineNumber++;
  161.     return( CurrentChar = LineBuffer );
  162. }
  163. void
  164. McSkipLine( void )
  165. {
  166.     CurrentChar = NULL;
  167. }
  168. /*++
  169. Routine Description:
  170.    This retrieves the character at the current position of the line
  171.    buffer then advances to the next position. If the end of the line
  172.    is reached another line is retrieve. If the end of the file is reached
  173.    this returns with a NULL character. One is optionally able to flush
  174.    the white space from the line.
  175. Arguments:
  176.    A boolean specifying whether whitespace should be consider significant.
  177. Return Value:
  178.    Returns the character in the current line.
  179. --*/
  180. char
  181. McGetChar(
  182.     BOOLEAN SkipWhiteSpace
  183.     )
  184. {
  185.     BOOLEAN SawWhiteSpace;
  186.     BOOLEAN SawNewLine;
  187.     PCOMMENT_INFO p;
  188.     SawWhiteSpace = FALSE;
  189. tryagain:
  190.     SawNewLine = FALSE;
  191.     if (CurrentChar == NULL) {
  192.         McGetLine();
  193.         if (CurrentChar == NULL) {
  194.             return( '' );
  195.             }
  196.         SawNewLine = TRUE;
  197.         }
  198.     if (SkipWhiteSpace) {
  199.         while (*CurrentChar <= ' ') {
  200.             SawWhiteSpace = TRUE;
  201.             if (!*CurrentChar++) {
  202.                 CurrentChar = NULL;
  203.                 break;
  204.                 }
  205.             }
  206.         }
  207.     if (SawNewLine) {
  208.         if (CurrentChar != NULL && *CurrentChar == MCCHAR_END_OF_LINE_COMMENT) {
  209.             p = malloc( sizeof( *p ) + strlen( ++CurrentChar ) );
  210.             p->Next = NULL;
  211.             strcpy( p->Text, CurrentChar );
  212.             if (CurrentComment == NULL) {
  213.                 Comments = p;
  214.                 }
  215.             else {
  216.                 CurrentComment->Next = p;
  217.                 }
  218.             CurrentComment = p;
  219.             CurrentChar = NULL;
  220.             }
  221.         }
  222.     if (CurrentChar == NULL && SkipWhiteSpace) {
  223.         goto tryagain;
  224.         }
  225.     if (SawWhiteSpace) {
  226.         return( ' ' );
  227.         }
  228.     else {
  229.         return( *CurrentChar++ );
  230.         }
  231. }
  232. void
  233. McFlushComments( void )
  234. {
  235.     PCOMMENT_INFO p;
  236.     while (p = Comments) {
  237.         fprintf( HeaderFile, "%s", p->Text );
  238.         Comments = Comments->Next;
  239.         free( p );
  240.         }
  241.     Comments = NULL;
  242.     CurrentComment = NULL;
  243.     fflush( HeaderFile );
  244.     return;
  245. }
  246. void
  247. McUnGetChar(
  248.     char c
  249.     )
  250. {
  251.     if (CurrentChar > LineBuffer) {
  252.         *--CurrentChar = c;
  253.         }
  254.     else {
  255.         LineBuffer[ 0 ] = c;
  256.         LineBuffer[ 1 ] = '';
  257.         CurrentChar = LineBuffer;
  258.         }
  259. }
  260. /*++
  261. Routine Description:
  262.     Breaks input line into "tokens values" as defined in MC.H.
  263. Arguments:
  264.     A boolean designating whether keywords are required.
  265. Return Value:
  266.    Returns the the token corresponding to the "token value" For example
  267.    with a token of type MCTOK_NUMBER the value would be a string
  268.    representation of an integer.
  269. --*/
  270. unsigned int
  271. McGetToken(
  272.     BOOLEAN KeywordExpected
  273.     )
  274. {
  275.     char c, *dst;
  276.     if (ReturnCurrentToken) {
  277.         ReturnCurrentToken = FALSE;
  278.         if (Token == MCTOK_NAME && KeywordExpected) {
  279.             TokenKeyword = McFindName( KeywordNames, TokenCharValue );
  280.             if (TokenKeyword == NULL) {
  281.                 McInputError( "expected keyword - %s", TRUE, TokenCharValue );
  282.                 Token = MCTOK_END_OF_FILE;
  283.                 }
  284.             else {
  285.                 Token = (unsigned int)TokenKeyword->Id;
  286.                 }
  287.             }
  288.         return( Token );
  289.         }
  290.     Token = MCTOK_END_OF_FILE;
  291.     dst = TokenCharValue;
  292.     *dst = '';
  293.     TokenNumericValue = 0L;
  294.     while (TRUE) {
  295.         c = McGetChar( (BOOLEAN)(Token == MCTOK_END_OF_FILE) );
  296.         if (Token == MCTOK_NUMBER) {
  297.             if (isdigit( c ) ||
  298.                 c == 'x' ||
  299.                 (c >= 'a' && c <= 'f') ||
  300.                 (c >= 'A' && c <= 'F')
  301.                ) {
  302.                 *dst++ = c;
  303.                 }
  304.             else {
  305.                 McUnGetChar( c );
  306.                 *dst = '';
  307.                 if (!McCharToInteger( TokenCharValue, 0, &TokenNumericValue )) {
  308.                     McInputError( "invalid number - %s", TRUE, TokenCharValue );
  309.                     Token = MCTOK_END_OF_FILE;
  310.                     }
  311.                 else {
  312.                     return( Token );
  313.                     }
  314.                 }
  315.             }
  316.         else
  317.         if (Token == MCTOK_NAME) {
  318.             if (iscsym( c )) {
  319.                 *dst++ = c;
  320.                 }
  321.             else {
  322.                 McUnGetChar( c );
  323.                 *dst = '';
  324.                 if (KeywordExpected) {
  325.                     TokenKeyword = McFindName( KeywordNames, TokenCharValue );
  326.                     if (TokenKeyword == NULL) {
  327.                         McInputError( "expected keyword - %s", TRUE, TokenCharValue );
  328.                         Token = MCTOK_END_OF_FILE;
  329.                         }
  330.                     else {
  331.                         Token = (unsigned int)TokenKeyword->Id;
  332.                         }
  333.                     }
  334.                 return( Token );
  335.                 }
  336.             }
  337.         else
  338.         if (isdigit( c )) {
  339.             *dst++ = c;
  340.             Token = MCTOK_NUMBER;
  341.             }
  342.         else
  343.         if (iscsymf( c )) {
  344.             *dst++ = c;
  345.             Token = MCTOK_NAME;
  346.             }
  347.         else
  348.         if (c == '=') {
  349.             *dst++ = c;
  350.             *dst = '';
  351.             Token = MCTOK_EQUAL;
  352.             return( Token );
  353.             }
  354.         else
  355.         if (c == '(') {
  356.             *dst++ = c;
  357.             *dst = '';
  358.             Token = MCTOK_LEFT_PAREN;
  359.             return( Token );
  360.             }
  361.         else
  362.         if (c == ')') {
  363.             *dst++ = c;
  364.             *dst = '';
  365.             Token = MCTOK_RIGHT_PAREN;
  366.             return( Token );
  367.             }
  368.         else
  369.         if (c == ':') {
  370.             *dst++ = c;
  371.             *dst = '';
  372.             Token = MCTOK_COLON;
  373.             return( Token );
  374.             }
  375.         else
  376.         if (c == '+') {
  377.             *dst++ = c;
  378.             *dst = '';
  379.             Token = MCTOK_PLUS;
  380.             return( Token );
  381.             }
  382.         else
  383.         if (c == ' ') {
  384.             }
  385.         else
  386.         if (c == MCCHAR_END_OF_LINE_COMMENT) {
  387.             Token = MCTOK_END_OF_LINE_COMMENT;
  388.             strcpy( TokenCharValue, CurrentChar );
  389.             CurrentChar = NULL;
  390.             return( Token );
  391.             }
  392.         else
  393.         if (c == '') {
  394.             return( Token );
  395.             }
  396.         else {
  397.             McInputError( "invalid character '%c'", TRUE, (PVOID)(ULONG)(UCHAR)c );
  398.             }
  399.         }
  400. }
  401. void
  402. McUnGetToken( void )
  403. {
  404.     ReturnCurrentToken = TRUE;
  405. }
  406. char *
  407. McSkipWhiteSpace(
  408.     char *s
  409.     )
  410. {
  411.     while (*s <= ' ') {
  412.         if (!*s++) {
  413.             s = NULL;
  414.             break;
  415.             }
  416.         }
  417.     return( s );
  418. }