@@ -80,6 +80,8 @@ RCParser::ParseType RCParser::parseSingleResource() {
80
80
Result = parseIconResource ();
81
81
else if (TypeToken->equalsLower (" MENU" ))
82
82
Result = parseMenuResource ();
83
+ else if (TypeToken->equalsLower (" MENUEX" ))
84
+ Result = parseMenuExResource ();
83
85
else if (TypeToken->equalsLower (" RCDATA" ))
84
86
Result = parseUserDefinedResource (RkRcData);
85
87
else if (TypeToken->equalsLower (" VERSIONINFO" ))
@@ -499,7 +501,7 @@ RCParser::ParseType RCParser::parseUserDefinedResource(IntOrString Type) {
499
501
case Kind::String:
500
502
case Kind::Identifier:
501
503
return std::make_unique<UserDefinedResource>(Type, read ().value (),
502
- MemoryFlags);
504
+ MemoryFlags);
503
505
default :
504
506
break ;
505
507
}
@@ -518,7 +520,7 @@ RCParser::ParseType RCParser::parseUserDefinedResource(IntOrString Type) {
518
520
}
519
521
520
522
return std::make_unique<UserDefinedResource>(Type, std::move (Data),
521
- MemoryFlags);
523
+ MemoryFlags);
522
524
}
523
525
524
526
RCParser::ParseType RCParser::parseVersionInfoResource () {
@@ -557,7 +559,8 @@ Expected<Control> RCParser::parseControl() {
557
559
IntOrString Class;
558
560
std::optional<IntWithNotMask> Style;
559
561
if (ClassUpper == " CONTROL" ) {
560
- // CONTROL text, id, class, style, x, y, width, height [, exstyle] [, helpID]
562
+ // CONTROL text, id, class, style, x, y, width, height [, exstyle] [,
563
+ // helpID]
561
564
ASSIGN_OR_RETURN (ClassStr, readString ());
562
565
RETURN_IF_ERROR (consumeType (Kind::Comma));
563
566
Class = *ClassStr;
@@ -589,8 +592,8 @@ Expected<Control> RCParser::parseControl() {
589
592
HelpID = *Val;
590
593
}
591
594
592
- return Control (*ClassResult, Caption, *ID, (*Args)[0 ], (*Args)[1 ],
593
- (*Args)[2 ], (*Args)[ 3 ], Style, ExStyle, HelpID, Class);
595
+ return Control (*ClassResult, Caption, *ID, (*Args)[0 ], (*Args)[1 ], (*Args)[ 2 ],
596
+ (*Args)[3 ], Style, ExStyle, HelpID, Class);
594
597
}
595
598
596
599
RCParser::ParseType RCParser::parseBitmapResource () {
@@ -620,7 +623,14 @@ RCParser::ParseType RCParser::parseMenuResource() {
620
623
ASSIGN_OR_RETURN (OptStatements, parseOptionalStatements ());
621
624
ASSIGN_OR_RETURN (Items, parseMenuItemsList ());
622
625
return std::make_unique<MenuResource>(std::move (*OptStatements),
623
- std::move (*Items), MemoryFlags);
626
+ std::move (*Items), MemoryFlags);
627
+ }
628
+
629
+ RCParser::ParseType RCParser::parseMenuExResource () {
630
+ uint16_t MemoryFlags =
631
+ parseMemoryFlags (MenuExResource::getDefaultMemoryFlags ());
632
+ ASSIGN_OR_RETURN (Items, parseMenuExItemsList ());
633
+ return std::make_unique<MenuExResource>(std::move (*Items), MemoryFlags);
624
634
}
625
635
626
636
Expected<MenuDefinitionList> RCParser::parseMenuItemsList () {
@@ -682,14 +692,103 @@ Expected<MenuDefinitionList> RCParser::parseMenuItemsList() {
682
692
return std::move (List);
683
693
}
684
694
695
+ Expected<MenuDefinitionList> RCParser::parseMenuExItemsList () {
696
+ RETURN_IF_ERROR (consumeType (Kind::BlockBegin));
697
+
698
+ MenuDefinitionList List;
699
+
700
+ // Read a set of items. Each item is of one of two kinds:
701
+ // MENUITEM caption:String [,[id][, [type][, state]]]]
702
+ // POPUP caption:String [,[id][, [type][, [state][, helpID]]]] { popupBody }
703
+ while (!consumeOptionalType (Kind::BlockEnd)) {
704
+ ASSIGN_OR_RETURN (ItemTypeResult, readIdentifier ());
705
+
706
+ bool IsMenuItem = ItemTypeResult->equals_insensitive (" MENUITEM" );
707
+ bool IsPopup = ItemTypeResult->equals_insensitive (" POPUP" );
708
+ if (!IsMenuItem && !IsPopup)
709
+ return getExpectedError (" MENUITEM, POPUP, END or '}'" , true );
710
+
711
+ // Not a separator. Read the caption.
712
+ ASSIGN_OR_RETURN (CaptionResult, readString ());
713
+
714
+ // If MENUITEM, expect [,[id][, [type][, state]]]]
715
+ if (IsMenuItem) {
716
+ uint32_t MenuId = 0 ;
717
+ uint32_t MenuType = 0 ;
718
+ uint32_t MenuState = 0 ;
719
+
720
+ if (consumeOptionalType (Kind::Comma)) {
721
+ auto IntId = readInt ();
722
+ if (IntId) {
723
+ MenuId = *IntId;
724
+ }
725
+ if (consumeOptionalType (Kind::Comma)) {
726
+ auto IntType = readInt ();
727
+ if (IntType) {
728
+ MenuType = *IntType;
729
+ }
730
+ if (consumeOptionalType (Kind::Comma)) {
731
+ auto IntState = readInt ();
732
+ if (IntState) {
733
+ MenuState = *IntState;
734
+ }
735
+ }
736
+ }
737
+ }
738
+ List.addDefinition (std::make_unique<MenuExItem>(*CaptionResult, MenuId,
739
+ MenuType, MenuState));
740
+ continue ;
741
+ }
742
+
743
+ assert (IsPopup);
744
+
745
+ uint32_t PopupId = 0 ;
746
+ uint32_t PopupType = 0 ;
747
+ uint32_t PopupState = 0 ;
748
+ uint32_t PopupHelpID = 0 ;
749
+
750
+ if (consumeOptionalType (Kind::Comma)) {
751
+ auto IntId = readInt ();
752
+ if (IntId) {
753
+ PopupId = *IntId;
754
+ }
755
+ if (consumeOptionalType (Kind::Comma)) {
756
+ auto IntType = readInt ();
757
+ if (IntType) {
758
+ PopupType = *IntType;
759
+ }
760
+ if (consumeOptionalType (Kind::Comma)) {
761
+ auto IntState = readInt ();
762
+ if (IntState) {
763
+ PopupState = *IntState;
764
+ }
765
+ if (consumeOptionalType (Kind::Comma)) {
766
+ auto IntHelpID = readInt ();
767
+ if (IntHelpID) {
768
+ PopupHelpID = *IntHelpID;
769
+ }
770
+ }
771
+ }
772
+ }
773
+ }
774
+ // If POPUP, read submenu items recursively.
775
+ ASSIGN_OR_RETURN (SubMenuResult, parseMenuExItemsList ());
776
+ List.addDefinition (std::make_unique<PopupExItem>(
777
+ *CaptionResult, PopupId, PopupType, PopupState, PopupHelpID,
778
+ std::move (*SubMenuResult)));
779
+ }
780
+
781
+ return std::move (List);
782
+ }
783
+
685
784
RCParser::ParseType RCParser::parseStringTableResource () {
686
785
uint16_t MemoryFlags =
687
786
parseMemoryFlags (StringTableResource::getDefaultMemoryFlags ());
688
787
ASSIGN_OR_RETURN (OptStatements, parseOptionalStatements ());
689
788
RETURN_IF_ERROR (consumeType (Kind::BlockBegin));
690
789
691
790
auto Table = std::make_unique<StringTableResource>(std::move (*OptStatements),
692
- MemoryFlags);
791
+ MemoryFlags);
693
792
694
793
// Read strings until we reach the end of the block.
695
794
while (!consumeOptionalType (Kind::BlockEnd)) {
@@ -753,7 +852,7 @@ Expected<std::unique_ptr<VersionInfoStmt>> RCParser::parseVersionInfoStmt() {
753
852
PrecedingCommas.push_back (HadComma);
754
853
}
755
854
return std::make_unique<VersionInfoValue>(*KeyResult, std::move (Values),
756
- std::move (PrecedingCommas));
855
+ std::move (PrecedingCommas));
757
856
}
758
857
759
858
return getExpectedError (" BLOCK or VALUE" , true );
@@ -835,7 +934,7 @@ RCParser::ParseOptionType RCParser::parseFontStmt(OptStmtType DialogType) {
835
934
}
836
935
}
837
936
return std::make_unique<FontStmt>(*SizeResult, *NameResult, FontWeight,
838
- FontItalic, FontCharset);
937
+ FontItalic, FontCharset);
839
938
}
840
939
841
940
RCParser::ParseOptionType RCParser::parseStyleStmt () {
0 commit comments