home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / mc / mclex.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  12KB  |  525 lines

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