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 / mcparse.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  21KB  |  591 lines

  1. /*++
  2.  
  3. Copyright (c) 1991-1997 Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     mcparse.c
  8.  
  9. Abstract:
  10.  
  11.     This file contains the parse logic for the Win32 Message Compiler (MC)
  12.  
  13.  
  14. --*/
  15.  
  16. #include "mc.h"
  17.  
  18. BOOLEAN
  19. McParseFile( void )
  20. {
  21.     unsigned int t;
  22.     BOOLEAN FirstMessageDefinition = TRUE;
  23.     PNAME_INFO p;
  24.  
  25.     if (!McOpenInputFile()) {
  26.         fprintf( stderr, "MC: Unable to open %s for input\n", MessageFileName );
  27.         return( FALSE );
  28.         }
  29.  
  30.     fprintf( stderr, "MC: Compiling %s\n", MessageFileName );
  31.     while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  32.         switch (t) {
  33.         case MCTOK_MSGIDTYPE_KEYWORD:
  34.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  35.                 if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  36.                     MessageIdTypeName = McMakeString( TokenCharValue );
  37.                     }
  38.                 else {
  39.                     McInputError( "Symbol name must follow %s=", TRUE, TokenKeyword->Name );
  40.                     return( FALSE );
  41.                     }
  42.                 }
  43.             else {
  44.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  45.                 return( FALSE );
  46.                 }
  47.             break;
  48.  
  49.         case MCTOK_SEVNAMES_KEYWORD:
  50.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  51.                 if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
  52.                     if (!McParseNameList( &SeverityNames, FALSE, 0x3L )) {
  53.                         return( FALSE );
  54.                         }
  55.                     }
  56.                 else {
  57.                     McInputError( "Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
  58.                     return( FALSE );
  59.                     }
  60.                 }
  61.             else {
  62.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  63.                 return( FALSE );
  64.                 }
  65.             break;
  66.  
  67.         case MCTOK_FACILITYNAMES_KEYWORD:
  68.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  69.                 if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
  70.                     if (!McParseNameList( &FacilityNames, FALSE, 0xFFFL )) {
  71.                         return( FALSE );
  72.                         }
  73.                     }
  74.                 else {
  75.                     McInputError( "Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
  76.                     return( FALSE );
  77.                     }
  78.                 }
  79.             else {
  80.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  81.                 return( FALSE );
  82.                 }
  83.             break;
  84.  
  85.         case MCTOK_LANGNAMES_KEYWORD:
  86.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  87.                 if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
  88.                     if (!McParseNameList( &LanguageNames, TRUE, 0xFFFFL )) {
  89.                         return( FALSE );
  90.                         }
  91.                     }
  92.                 else {
  93.                     McInputError( "Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
  94.                     return( FALSE );
  95.                     }
  96.                 }
  97.             else {
  98.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  99.                 return( FALSE );
  100.                 }
  101.             break;
  102.  
  103.         case MCTOK_MESSAGEID_KEYWORD:
  104.             McUnGetToken();
  105.             if (FirstMessageDefinition) {
  106.                 FirstMessageDefinition = FALSE;
  107.                 McFlushComments();
  108.                 fprintf( HeaderFile, "//\r\n" );
  109.                 fprintf( HeaderFile, "//  Values are 32 bit values layed out as follows:\r\n" );
  110.                 fprintf( HeaderFile, "//\r\n" );
  111.                 fprintf( HeaderFile, "//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r\n" );
  112.                 fprintf( HeaderFile, "//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\r\n" );
  113.                 fprintf( HeaderFile, "//  +---+-+-+-----------------------+-------------------------------+\r\n" );
  114.                 fprintf( HeaderFile, "//  |Sev|C|R|     Facility          |               Code            |\r\n" );
  115.                 fprintf( HeaderFile, "//  +---+-+-+-----------------------+-------------------------------+\r\n" );
  116.                 fprintf( HeaderFile, "//\r\n" );
  117.                 fprintf( HeaderFile, "//  where\r\n" );
  118.                 fprintf( HeaderFile, "//\r\n" );
  119.                 fprintf( HeaderFile, "//      Sev - is the severity code\r\n" );
  120.                 fprintf( HeaderFile, "//\r\n" );
  121.                 fprintf( HeaderFile, "//          00 - Success\r\n" );
  122.                 fprintf( HeaderFile, "//          01 - Informational\r\n" );
  123.                 fprintf( HeaderFile, "//          10 - Warning\r\n" );
  124.                 fprintf( HeaderFile, "//          11 - Error\r\n" );
  125.                 fprintf( HeaderFile, "//\r\n" );
  126.                 fprintf( HeaderFile, "//      C - is the Customer code flag\r\n" );
  127.                 fprintf( HeaderFile, "//\r\n" );
  128.                 fprintf( HeaderFile, "//      R - is a reserved bit\r\n" );
  129.                 fprintf( HeaderFile, "//\r\n" );
  130.                 fprintf( HeaderFile, "//      Facility - is the facility code\r\n" );
  131.                 fprintf( HeaderFile, "//\r\n" );
  132.                 fprintf( HeaderFile, "//      Code - is the facility's status code\r\n" );
  133.                 fprintf( HeaderFile, "//\r\n" );
  134.  
  135.                 fprintf( HeaderFile, "//\r\n" );
  136.                 fprintf( HeaderFile, "// Define the facility codes\r\n" );
  137.                 fprintf( HeaderFile, "//\r\n" );
  138.                 p = FacilityNames;
  139.                 while( p ) {
  140.                     if (p->Value) {
  141.                         fprintf( HeaderFile, GenerateDecimalValues ?
  142.                                              "#define %-32s %ld\r\n" :
  143.                                              "#define %-32s 0x%lX\r\n",
  144.                                  p->Value, p->Id
  145.                                );
  146.                         }
  147.  
  148.                     p = p->Next;
  149.                     }
  150.                 fprintf( HeaderFile, "\r\n" );
  151.                 fprintf( HeaderFile, "\r\n" );
  152.  
  153.                 fprintf( HeaderFile, "//\r\n" );
  154.                 fprintf( HeaderFile, "// Define the severity codes\r\n" );
  155.                 fprintf( HeaderFile, "//\r\n" );
  156.                 p = SeverityNames;
  157.                 while( p ) {
  158.                     if (p->Value) {
  159.                         fprintf( HeaderFile, GenerateDecimalValues ?
  160.                                              "#define %-32s %ld\r\n" :
  161.                                              "#define %-32s 0x%lX\r\n",
  162.                                  p->Value, p->Id
  163.                                );
  164.                         }
  165.  
  166.                     p = p->Next;
  167.                     }
  168.                 fprintf( HeaderFile, "\r\n" );
  169.                 fprintf( HeaderFile, "\r\n" );
  170.                 }
  171.  
  172.             if (!McParseMessageDefinition()) {
  173.                 return( FALSE );
  174.                 }
  175.             break;
  176.  
  177.         default:
  178.             McInputError( "Invalid message file token - '%s'", TRUE, TokenCharValue );
  179.             return( FALSE );
  180.             break;
  181.         }
  182.     }
  183.  
  184.     McFlushComments();
  185.     return( TRUE );
  186. }
  187.  
  188.  
  189. BOOLEAN
  190. McParseMessageDefinition( void )
  191. {
  192.     unsigned int t;
  193.     PMESSAGE_INFO MessageInfo;
  194.     BOOLEAN MessageIdSeen;
  195.     PMESSAGE_INFO MessageInfoTemp;
  196.  
  197.     McFlushComments();
  198.  
  199.     MessageInfo = malloc( sizeof( *MessageInfo ) );
  200.     MessageInfo->Next = NULL;
  201.     MessageInfo->Id = 0;
  202.     MessageInfo->Method = MSG_PLUS_ONE;
  203.     MessageInfo->SymbolicName = NULL;
  204.     MessageInfo->EndOfLineComment = NULL;
  205.     MessageInfo->MessageText = NULL;
  206.     MessageIdSeen = FALSE;
  207.  
  208.     while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  209.         switch (t) {
  210.         case MCTOK_MESSAGEID_KEYWORD:
  211.             if (MessageIdSeen) {
  212.                 McInputError( "Invalid message definition - text missing.", TRUE, NULL );
  213.                 return( FALSE );
  214.                 }
  215.  
  216.             MessageIdSeen = TRUE;
  217.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  218.                 if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  219.                     MessageInfo->Id = TokenNumericValue;
  220.                     MessageInfo->Method = MSG_ABSOLUTE;
  221.                     }
  222.                 else
  223.                 if (t == MCTOK_PLUS) {
  224.                     if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  225.                         MessageInfo->Id = TokenNumericValue;
  226.                         MessageInfo->Method = MSG_PLUS_VALUE;
  227.                         }
  228.                     else {
  229.                         McInputError( "Number must follow %s=+", TRUE, TokenKeyword->Name );
  230.                         return( FALSE );
  231.                         }
  232.                     }
  233.                 else {
  234.                     McUnGetToken();
  235.                     }
  236.  
  237.                 }
  238.             else {
  239.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  240.                 return( FALSE );
  241.                 }
  242.             break;
  243.  
  244.         case MCTOK_SEVERITY_KEYWORD:
  245.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  246.                 if (!McParseName( SeverityNames, &CurrentSeverityName )) {
  247.                     return( FALSE );
  248.                     }
  249.                 }
  250.             else {
  251.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  252.                 return( FALSE );
  253.                 }
  254.             break;
  255.  
  256.         case MCTOK_FACILITY_KEYWORD:
  257.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  258.                 if (!McParseName( FacilityNames, &CurrentFacilityName )) {
  259.                     return( FALSE );
  260.                     }
  261.                 }
  262.             else {
  263.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  264.                 return( FALSE );
  265.                 }
  266.             break;
  267.  
  268.         case MCTOK_SYMBOLNAME_KEYWORD:
  269.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  270.                 if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  271.                     MessageInfo->SymbolicName = McMakeString( TokenCharValue );
  272.                     }
  273.                 else {
  274.                     McInputError( "Symbol name must follow %s=+", TRUE, TokenKeyword->Name );
  275.                     return( FALSE );
  276.                     }
  277.                 }
  278.             else {
  279.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  280.                 return( FALSE );
  281.                 }
  282.             break;
  283.  
  284.  
  285.         case MCTOK_END_OF_LINE_COMMENT:
  286.             MessageInfo->EndOfLineComment = McMakeString( TokenCharValue );
  287.             break;
  288.  
  289.         case MCTOK_LANGUAGE_KEYWORD:
  290.             McUnGetToken();
  291.  
  292.  
  293.             if (MessageInfo->Method == MSG_PLUS_ONE) {
  294.                 MessageInfo->Id = CurrentFacilityName->LastId + 1;
  295.                 }
  296.             else
  297.             if (MessageInfo->Method == MSG_PLUS_VALUE) {
  298.                 MessageInfo->Id = CurrentFacilityName->LastId + MessageInfo->Id;
  299.                 }
  300.  
  301.             if (MessageInfo->Id > 0xFFFFL) {
  302.                 McInputError( "Message Id value (%lx) too large", TRUE, (PVOID)MessageInfo->Id );
  303.                 return( FALSE );
  304.                 }
  305.  
  306.             MessageInfo->Id |= (CurrentSeverityName->Id << 30) |
  307.                                CustomerMsgIdBit |
  308.                                (CurrentFacilityName->Id << 16);
  309.  
  310.             fprintf( HeaderFile, "//\r\n" );
  311.             if (MessageInfo->SymbolicName) {
  312.                 fprintf( HeaderFile, "// MessageId: %s\r\n",
  313.                                      MessageInfo->SymbolicName
  314.                        );
  315.                 }
  316.             else {
  317.                 fprintf( HeaderFile, "// MessageId: 0x%08lXL (No symbolic name defined)\r\n",
  318.                                      MessageInfo->Id
  319.                        );
  320.                 }
  321.  
  322.             fprintf( HeaderFile, "//\r\n" );
  323.             fprintf( HeaderFile, "// MessageText:\r\n" );
  324.             fprintf( HeaderFile, "//\r\n" );
  325.  
  326.             if (McParseMessageText( MessageInfo )) {
  327.                 fprintf( HeaderFile, "//\r\n" );
  328.                 if (MessageInfo->SymbolicName) {
  329.  
  330.                     if (MessageIdTypeName != NULL) {
  331.                         fprintf( HeaderFile, GenerateDecimalValues ?
  332.                                              "#define %-32s ((%s)%ldL)" :
  333.                                              "#define %-32s ((%s)0x%08lXL)",
  334.                                              MessageInfo->SymbolicName,
  335.                                              MessageIdTypeName,
  336.                                              MessageInfo->Id
  337.                                );
  338.                         }
  339.                     else {
  340.                         fprintf( HeaderFile, GenerateDecimalValues ?
  341.                                              "#define %-32s %ldL" :
  342.                                              "#define %-32s 0x%08lXL",
  343.                                              MessageInfo->SymbolicName,
  344.                                              MessageInfo->Id
  345.                                );
  346.                         }
  347.                     }
  348.  
  349.                 if (MessageInfo->EndOfLineComment) {
  350.                     fprintf( HeaderFile, "    %s", MessageInfo->EndOfLineComment );
  351.                     }
  352.                 else {
  353.                     fprintf( HeaderFile, "\r\n" );
  354.                     }
  355.                 fprintf( HeaderFile, "\r\n" );
  356.  
  357.                 if (Messages == NULL) {
  358.                     Messages = MessageInfo;
  359.                     }
  360.                 else {
  361.                     MessageInfoTemp = Messages;
  362.  
  363.                     //
  364.                     //  Scan the existing messages to see if this message
  365.                     //  exists in the message file.
  366.                     //
  367.                     //  If it does, generate and error for the user.
  368.                     //
  369.  
  370.                     while (MessageInfoTemp != NULL) {
  371.  
  372.                         if (MessageInfoTemp->Id == MessageInfo->Id) {
  373.                             McInputError( "Duplicate message ID - 0x%lx", FALSE, (PVOID)MessageInfo->Id );
  374.                             }
  375.  
  376.                         MessageInfoTemp = MessageInfoTemp->Next;
  377.                         }
  378.  
  379.                     CurrentMessage->Next = MessageInfo;
  380.                     }
  381.  
  382.                 CurrentMessage = MessageInfo;
  383.                 CurrentFacilityName->LastId = MessageInfo->Id & 0xFFFF;
  384.                 return( TRUE );
  385.                 }
  386.             else {
  387.                 return( FALSE );
  388.                 }
  389.  
  390.         default:
  391.             McInputError( "Invalid message definition token - '%s'", TRUE, TokenCharValue );
  392.             return( FALSE );
  393.             }
  394.         }
  395.  
  396.     return( FALSE );
  397. }
  398.  
  399.  
  400. char MessageTextBuffer[ 8192 ];
  401.  
  402. BOOLEAN
  403. McParseMessageText(
  404.     PMESSAGE_INFO MessageInfo
  405.     )
  406. {
  407.     PLANGUAGE_INFO MessageText, *pp;
  408.     char *src, *dst;
  409.     unsigned int t, n;
  410.     BOOLEAN FirstLanguageProcessed;
  411.  
  412.     pp = &MessageInfo->MessageText;
  413.  
  414.     FirstLanguageProcessed = FALSE;
  415.     while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  416.         if (t == MCTOK_LANGUAGE_KEYWORD) {
  417.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  418.                 if (!McParseName( LanguageNames, &CurrentLanguageName )) {
  419.                     return( FALSE );
  420.                     }
  421.                 }
  422.             else {
  423.                 McInputError( "Equal sign must follow %s", TRUE, TokenKeyword->Name );
  424.                 return( FALSE );
  425.                 }
  426.             }
  427.         else {
  428.             McUnGetToken();
  429.             break;
  430.             }
  431.  
  432.         MessageText = malloc( sizeof( *MessageText ) );
  433.         MessageText->Next = NULL;
  434.         MessageText->Id = CurrentLanguageName->Id;
  435.         MessageText->Length = 0;
  436.         MessageText->Text = NULL;
  437.  
  438.         dst = MessageTextBuffer;
  439.         while (src = McGetLine()) {
  440.             if (!strcmp( src, ".\r\n" )) {
  441.                 if (MessageText->Length == 0) {
  442.                     if (MessageInfo->SymbolicName) {
  443.                         strcpy( dst, MessageInfo->SymbolicName );
  444.                         }
  445.                     else {
  446.                         sprintf( dst, "No symbolic name defined for0x%08lXL" );
  447.                         }
  448.  
  449.                     strcat( dst, "\r\n" );
  450.                     if (!FirstLanguageProcessed) {
  451.                         fprintf( HeaderFile, "//  %s", dst );
  452.                         }
  453.  
  454.                     n = strlen( dst );
  455.                     dst += n;
  456.                     MessageText->Length += n;
  457.                     }
  458.  
  459.                 McSkipLine();
  460.                 break;
  461.                 }
  462.             else
  463.             if (!strnicmp( src, "LanguageId=", 11 ) ||
  464.                 !strnicmp( src, "MessageId=", 10 )
  465.                ) {
  466.                 McInputError( "Unterminated message definition", TRUE, NULL );
  467.                 return( FALSE );
  468.                 }
  469.  
  470.             if (!FirstLanguageProcessed) {
  471.                 fprintf( HeaderFile, "//  %s", src );
  472.                 }
  473.  
  474.             n = strlen( src );
  475.             if (MessageText->Length + n > sizeof( MessageTextBuffer )) {
  476.                 McInputError( "Message text too long - > %ld", TRUE,
  477.                               (PVOID)(ULONG)sizeof( MessageTextBuffer )
  478.                             );
  479.                 return( FALSE );
  480.                 }
  481.  
  482.             strcpy( dst, src );
  483.             dst += n;
  484.             MessageText->Length += n;
  485.             }
  486.         *dst = '\0';
  487.  
  488.         n = ((USHORT)MessageText->Length)+1;
  489.         MessageText->Text = malloc( n );
  490.         memcpy( MessageText->Text, MessageTextBuffer, n );
  491.         *pp = MessageText;
  492.         pp = &MessageText->Next;
  493.         FirstLanguageProcessed = TRUE;
  494.         }
  495.  
  496.     return( TRUE );
  497. }
  498.  
  499.  
  500. BOOLEAN
  501. McParseNameList(
  502.     PNAME_INFO *NameListHead,
  503.     BOOLEAN ValueRequired,
  504.     ULONG MaximumValue
  505.     )
  506. {
  507.     unsigned int t;
  508.     PNAME_INFO p;
  509.     char *Name;
  510.     ULONG Id;
  511.     PVOID Value;
  512.  
  513.     while ((t = McGetToken( FALSE )) != MCTOK_END_OF_FILE) {
  514.         if (t == MCTOK_RIGHT_PAREN) {
  515.             return( TRUE );
  516.             }
  517.  
  518.         if (t == MCTOK_NAME) {
  519.             Name = McMakeString( TokenCharValue );
  520.             Id = 0;
  521.             Value = NULL;
  522.             if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  523.                 if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  524.                     Id = TokenNumericValue;
  525.                     if ((t = McGetToken( FALSE )) == MCTOK_COLON) {
  526.                         if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  527.                             Value = McMakeString( TokenCharValue );
  528.                             }
  529.                         else {
  530.                             McInputError( "File name must follow =%ld:", TRUE, (PVOID)Id );
  531.                             return( FALSE );
  532.                             }
  533.                         }
  534.                     else {
  535.                         if (ValueRequired) {
  536.                             McInputError( "Colon must follow =%ld", TRUE, (PVOID)Id );
  537.                             return( FALSE );
  538.                             }
  539.  
  540.                         McUnGetToken();
  541.                         }
  542.                     }
  543.                 else {
  544.                     McInputError( "Number must follow %s=", TRUE, Name );
  545.                     return( FALSE );
  546.                     }
  547.                 }
  548.             else {
  549.                 McInputError( "Equal sign name must follow %s", TRUE, Name );
  550.                 return( FALSE );
  551.                 }
  552.  
  553.             if (Id > MaximumValue) {
  554.                 McInputError( "Value is too large (> %lx)", TRUE, (PVOID)MaximumValue );
  555.                 return( FALSE );
  556.                 }
  557.  
  558.             p = McAddName( NameListHead, Name, Id, Value );
  559.             free( Name );
  560.             }
  561.         }
  562.  
  563.     return( FALSE );
  564. }
  565.  
  566. BOOLEAN
  567. McParseName(
  568.     PNAME_INFO NameListHead,
  569.     PNAME_INFO *Result
  570.     )
  571. {
  572.     unsigned int t;
  573.     PNAME_INFO p;
  574.  
  575.     if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  576.         p = McFindName( NameListHead, TokenCharValue );
  577.         if (p != NULL) {
  578.             *Result = p;
  579.             return( TRUE );
  580.             }
  581.         else {
  582.             McInputError( "Invalid name - %s", TRUE, TokenCharValue );
  583.             }
  584.         }
  585.     else {
  586.         McInputError( "Missing name after %s=", TRUE, TokenKeyword->Name );
  587.         }
  588.  
  589.     return( FALSE );
  590. }
  591.