Index: llvm/test/tools/llvm-rc/Inputs/parser-correct-everything.rc =================================================================== --- llvm/test/tools/llvm-rc/Inputs/parser-correct-everything.rc +++ llvm/test/tools/llvm-rc/Inputs/parser-correct-everything.rc @@ -61,7 +61,7 @@ LANGUAGE 1, 2 CHARACTERISTICS 50 VERSION 100 -FONT 12, "Arial" +FONT 12, "Arial", 500, 1, 13 CAPTION "RC parser dialog" STYLE 0x51234 BEGIN Index: llvm/test/tools/llvm-rc/Inputs/parser-dialog-simple-font.rc =================================================================== --- /dev/null +++ llvm/test/tools/llvm-rc/Inputs/parser-dialog-simple-font.rc @@ -0,0 +1,4 @@ +1 DIALOG 1, 2, 3, 4 +FONT 12, "Face", 100, 1, 0 +BEGIN +END Index: llvm/test/tools/llvm-rc/Inputs/tag-dialog-bad-style.rc =================================================================== --- /dev/null +++ llvm/test/tools/llvm-rc/Inputs/tag-dialog-bad-style.rc @@ -0,0 +1,2 @@ +1 DIALOG 1, 2, 3, 4 +STYLE 0xFFFF0001 {} Index: llvm/test/tools/llvm-rc/Inputs/tag-dialog-headers.rc =================================================================== --- /dev/null +++ llvm/test/tools/llvm-rc/Inputs/tag-dialog-headers.rc @@ -0,0 +1,53 @@ +1 DIALOGEX 1, 2, 3, 4 {} +2 DIALOG 1, 2, 3, 4 {} + +3 DIALOGEX 10000, 20000, 30000, 32767 +CAPTION "My Caption" {} +4 DIALOG -32768, 32767, 0, 32767 +CAPTION "My Caption" {} + +5 DIALOGEX 0, 1, 0, 9 +STYLE 0x01234567 {} +6 DIALOG 0, 1, 0, 9 +STYLE 0x01234567 {} + +7 DIALOGEX 8, 7, 6, 5 +FONT 50, "a" {} +8 DIALOG 8, 7, 6, 5 +FONT 50, "aaaa" {} +9 DIALOGEX 8, 7, 6, 5 +FONT 50, L"a" {} +10 DIALOG 8, 7, 6, 5 +FONT 50, L"aaaa" {} +11 DIALOGEX 1, 2, 3, 4 +FONT 50, "FONT", 51 {} +12 DIALOGEX 1, 2, 3, 4 +FONT 50, "FONT", 51, 52 {} +13 DIALOGEX 1, 2, 3, 4 +FONT 50, "FONT", 51, 52, 53 {} + +14 DIALOGEX 1, 1, 1, 1 +CAPTION "CAPTION" FONT 42, "FONT" {} +15 DIALOG 1, 1, 1, 1 +CAPTION "CAPTION" FONT 42, "FONT" {} + +16 DIALOGEX 2, 2, 2, 2 +CAPTION "CAPTION" FONT 42, "FONT" STYLE 0 {} +17 DIALOG 2, 2, 2, 2 +CAPTION "CAPTION" FONT 42, "FONT" STYLE 0 {} + +18 DIALOGEX 3, 3, 3, 3 +CAPTION "CAPTION" STYLE 0 {} +19 DIALOG 3, 3, 3, 3 +CAPTION "CAPTION" STYLE 0 {} + +20 DIALOGEX 4, 4, 4, 4 STYLE 0xFF00FF00 {} +21 DIALOG 4, 4, 4, 4 STYLE 0xFF00FF00 {} +22 DIALOGEX 4, 4, 4, 4 STYLE 0x00FF00FF {} +23 DIALOG 4, 4, 4, 4 STYLE 0x00FF00FF {} + +24 DIALOGEX 5, 5, 5, 5 CAPTION "" STYLE 0 {} +25 DIALOG 5, 5, 5, 5 CAPTION "" STYLE 0 {} + +26 DIALOGEX 1, 2, 3, 4, 5 {} + Index: llvm/test/tools/llvm-rc/parser.test =================================================================== --- llvm/test/tools/llvm-rc/parser.test +++ llvm/test/tools/llvm-rc/parser.test @@ -53,7 +53,7 @@ ; PGOOD-NEXT: Option: Language: 1, Sublanguage: 2 ; PGOOD-NEXT: Option: Characteristics: 50 ; PGOOD-NEXT: Option: Version: 100 -; PGOOD-NEXT: Option: Font: size = 12, face = "Arial" +; PGOOD-NEXT: Option: Font: size = 12, face = "Arial", weight = 500, italic, charset = 13 ; PGOOD-NEXT: Option: Caption: "RC parser dialog" ; PGOOD-NEXT: Option: Style: 332340 ; PGOOD-NEXT: Control (14): LTEXT, title: "Hello world!", loc: (20, 20), size: [50, 50] @@ -220,6 +220,11 @@ ; PDIALOG5: llvm-rc: Error parsing file: expected '-', '~', integer or '(', got "This shouldn't be here" +; RUN: not llvm-rc /dry-run /V %p/Inputs/parser-dialog-simple-font.rc 2>&1 | FileCheck %s --check-prefix PDIALOG6 + +; PDIALOG6: llvm-rc: Error parsing file: expected identifier, got , + + ; RUN: not llvm-rc /dry-run /V %p/Inputs/parser-versioninfo-wrong-fixed.rc 2>&1 | FileCheck %s --check-prefix PVERSIONINFO1 ; PVERSIONINFO1: llvm-rc: Error parsing file: expected fixed VERSIONINFO statement type, got WEIRDFIXED Index: llvm/test/tools/llvm-rc/tag-dialog.test =================================================================== --- llvm/test/tools/llvm-rc/tag-dialog.test +++ llvm/test/tools/llvm-rc/tag-dialog.test @@ -132,6 +132,393 @@ ; DIALOG-NEXT: ) +; RUN: llvm-rc /FO %t %p/Inputs/tag-dialog-headers.rc +; RUN: llvm-readobj %t | FileCheck %s --check-prefix=HEADERS + +; HEADERS: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 1 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 00008880 |................| +; HEADERS-NEXT: 0010: 00000100 02000300 04000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 2 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 00008880 00000000 00000100 02000300 |................| +; HEADERS-NEXT: 0010: 04000000 00000000 |........| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 3 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 52 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 0000C880 |................| +; HEADERS-NEXT: 0010: 00001027 204E3075 FF7F0000 00004D00 |...' N0u......M.| +; HEADERS-NEXT: 0020: 79002000 43006100 70007400 69006F00 |y. .C.a.p.t.i.o.| +; HEADERS-NEXT: 0030: 6E000000 |n...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 4 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 44 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0000C880 00000000 00000080 FF7F0000 |................| +; HEADERS-NEXT: 0010: FF7F0000 00004D00 79002000 43006100 |......M.y. .C.a.| +; HEADERS-NEXT: 0020: 70007400 69006F00 6E000000 |p.t.i.o.n...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 5 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 27452301 |............'E#.| +; HEADERS-NEXT: 0010: 00000000 01000000 09000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 6 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 27452301 00000000 00000000 01000000 |'E#.............| +; HEADERS-NEXT: 0010: 09000000 00000000 |........| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 7 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 42 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 40008880 |............@...| +; HEADERS-NEXT: 0010: 00000800 07000600 05000000 00000000 |................| +; HEADERS-NEXT: 0020: 32000000 00016100 0000 |2.....a...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 8 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 36 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 40008880 00000000 00000800 07000600 |@...............| +; HEADERS-NEXT: 0010: 05000000 00000000 32006100 61006100 |........2.a.a.a.| +; HEADERS-NEXT: 0020: 61000000 |a...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 9 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 42 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 40008880 |............@...| +; HEADERS-NEXT: 0010: 00000800 07000600 05000000 00000000 |................| +; HEADERS-NEXT: 0020: 32000000 00016100 0000 |2.....a...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 10 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 36 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 40008880 00000000 00000800 07000600 |@...............| +; HEADERS-NEXT: 0010: 05000000 00000000 32006100 61006100 |........2.a.a.a.| +; HEADERS-NEXT: 0020: 61000000 |a...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 11 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 48 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 40008880 |............@...| +; HEADERS-NEXT: 0010: 00000100 02000300 04000000 00000000 |................| +; HEADERS-NEXT: 0020: 32003300 00014600 4F004E00 54000000 |2.3...F.O.N.T...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 12 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 48 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 40008880 |............@...| +; HEADERS-NEXT: 0010: 00000100 02000300 04000000 00000000 |................| +; HEADERS-NEXT: 0020: 32003300 01014600 4F004E00 54000000 |2.3...F.O.N.T...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 13 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 48 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 40008880 |............@...| +; HEADERS-NEXT: 0010: 00000100 02000300 04000000 00000000 |................| +; HEADERS-NEXT: 0020: 32003300 01354600 4F004E00 54000000 |2.3..5F.O.N.T...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 14 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 62 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 4000C880 |............@...| +; HEADERS-NEXT: 0010: 00000100 01000100 01000000 00004300 |..............C.| +; HEADERS-NEXT: 0020: 41005000 54004900 4F004E00 00002A00 |A.P.T.I.O.N...*.| +; HEADERS-NEXT: 0030: 00000001 46004F00 4E005400 0000 |....F.O.N.T...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 15 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 50 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 4000C880 00000000 00000100 01000100 |@...............| +; HEADERS-NEXT: 0010: 01000000 00004300 41005000 54004900 |......C.A.P.T.I.| +; HEADERS-NEXT: 0020: 4F004E00 00002A00 46004F00 4E005400 |O.N...*.F.O.N.T.| +; HEADERS-NEXT: 0030: 0000 |..| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 16 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 62 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 4000C000 |............@...| +; HEADERS-NEXT: 0010: 00000200 02000200 02000000 00004300 |..............C.| +; HEADERS-NEXT: 0020: 41005000 54004900 4F004E00 00002A00 |A.P.T.I.O.N...*.| +; HEADERS-NEXT: 0030: 00000001 46004F00 4E005400 0000 |....F.O.N.T...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 17 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 50 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 4000C000 00000000 00000200 02000200 |@...............| +; HEADERS-NEXT: 0010: 02000000 00004300 41005000 54004900 |......C.A.P.T.I.| +; HEADERS-NEXT: 0020: 4F004E00 00002A00 46004F00 4E005400 |O.N...*.F.O.N.T.| +; HEADERS-NEXT: 0030: 0000 |..| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 18 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 46 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 0000C000 |................| +; HEADERS-NEXT: 0010: 00000300 03000300 03000000 00004300 |..............C.| +; HEADERS-NEXT: 0020: 41005000 54004900 4F004E00 0000 |A.P.T.I.O.N...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 19 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 38 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0000C000 00000000 00000300 03000300 |................| +; HEADERS-NEXT: 0010: 03000000 00004300 41005000 54004900 |......C.A.P.T.I.| +; HEADERS-NEXT: 0020: 4F004E00 0000 |O.N...| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 20 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 00FF00FF |................| +; HEADERS-NEXT: 0010: 00000400 04000400 04000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 21 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 00FF00FF 00000000 00000400 04000400 |................| +; HEADERS-NEXT: 0010: 04000000 00000000 |........| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 22 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 BF00FF00 |................| +; HEADERS-NEXT: 0010: 00000400 04000400 04000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 23 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: BF00FF00 00000000 00000400 04000400 |................| +; HEADERS-NEXT: 0010: 04000000 00000000 |........| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 24 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 00000000 0000C000 |................| +; HEADERS-NEXT: 0010: 00000500 05000500 05000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 25 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0000C000 00000000 00000500 05000500 |................| +; HEADERS-NEXT: 0010: 05000000 00000000 |........| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 26 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 05000000 00000000 00008880 |................| +; HEADERS-NEXT: 0010: 00000100 02000300 04000000 00000000 |................| +; HEADERS-NEXT: ) + ; RUN: not llvm-rc /FO %t %p/Inputs/tag-dialog-large-coord.rc 2>&1 | FileCheck %s --check-prefix COORD1 @@ -197,3 +584,9 @@ ; CTL-REF-ID: llvm-rc: Error in DIALOGEX statement (ID 1): ; CTL-REF-ID-NEXT: Error in CTEXT control (ID 42): ; CTL-REF-ID-NEXT: Control reference ID (65536) does not fit in 16 bits. + + +; RUN: not llvm-rc /FO %t %p/Inputs/tag-dialog-bad-style.rc 2>&1 | FileCheck %s --check-prefix STYLE + +; STYLE: llvm-rc: Error in DIALOG statement (ID 1): +; STYLE-NEXT: 16 higher bits of DIALOG resource style cannot be equal to 0xFFFF Index: llvm/tools/llvm-rc/ResourceFileWriter.h =================================================================== --- llvm/tools/llvm-rc/ResourceFileWriter.h +++ llvm/tools/llvm-rc/ResourceFileWriter.h @@ -35,8 +35,11 @@ Error visitHTMLResource(const RCResource *) override; Error visitMenuResource(const RCResource *) override; + Error visitCaptionStmt(const CaptionStmt *) override; Error visitCharacteristicsStmt(const CharacteristicsStmt *) override; + Error visitFontStmt(const FontStmt *) override; Error visitLanguageStmt(const LanguageResource *) override; + Error visitStyleStmt(const StyleStmt *) override; Error visitVersionStmt(const VersionStmt *) override; struct ObjectInfo { @@ -44,6 +47,17 @@ uint32_t Characteristics; uint32_t VersionInfo; + Optional Style; + StringRef Caption; + struct FontInfo { + uint32_t Size; + StringRef Typeface; + uint32_t Weight; + bool IsItalic; + uint32_t Charset; + }; + Optional Font; + ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {} } ObjectData; Index: llvm/tools/llvm-rc/ResourceFileWriter.cpp =================================================================== --- llvm/tools/llvm-rc/ResourceFileWriter.cpp +++ llvm/tools/llvm-rc/ResourceFileWriter.cpp @@ -224,6 +224,11 @@ return writeResource(Res, &ResourceFileWriter::writeDialogBody); } +Error ResourceFileWriter::visitCaptionStmt(const CaptionStmt *Stmt) { + ObjectData.Caption = Stmt->Value; + return Error::success(); +} + Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) { return writeResource(Res, &ResourceFileWriter::writeHTMLBody); } @@ -238,6 +243,16 @@ return Error::success(); } +Error ResourceFileWriter::visitFontStmt(const FontStmt *Stmt) { + RETURN_IF_ERROR(checkNumberFits(Stmt->Size, "Font size")); + RETURN_IF_ERROR(checkNumberFits(Stmt->Weight, "Font weight")); + RETURN_IF_ERROR(checkNumberFits(Stmt->Charset, "Font charset")); + ObjectInfo::FontInfo Font{Stmt->Size, Stmt->Name, Stmt->Weight, Stmt->Italic, + Stmt->Charset}; + ObjectData.Font.emplace(Font); + return Error::success(); +} + Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) { RETURN_IF_ERROR(checkNumberFits(Stmt->Lang, 10, "Primary language ID")); RETURN_IF_ERROR(checkNumberFits(Stmt->SubLang, 6, "Sublanguage ID")); @@ -245,6 +260,11 @@ return Error::success(); } +Error ResourceFileWriter::visitStyleStmt(const StyleStmt *Stmt) { + ObjectData.Style = Stmt->Value; + return Error::success(); +} + Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) { ObjectData.VersionInfo = Stmt->Value; return Error::success(); @@ -474,10 +494,36 @@ auto *Res = cast(Base); // Default style: WS_POPUP | WS_BORDER | WS_SYSMENU. - const uint32_t UsedStyle = 0x80880000; + const uint32_t DefaultStyle = 0x80880000; + const uint32_t StyleFontFlag = 0x40; + const uint32_t StyleCaptionFlag = 0x00C00000; + + uint32_t UsedStyle = ObjectData.Style.getValueOr(DefaultStyle); + if (ObjectData.Font) + UsedStyle |= StyleFontFlag; + else + UsedStyle &= ~StyleFontFlag; + + // Actually, in case of empty (but existent) caption, the examined field + // is equal to "\"\"". That's why empty captions are still noticed. + if (ObjectData.Caption != "") + UsedStyle |= StyleCaptionFlag; + + const uint16_t DialogExMagic = 0xFFFF; // Write DIALOG(EX) header prefix. These are pretty different. if (!Res->IsExtended) { + // We cannot let the higher word of DefaultStyle be equal to 0xFFFF. + // In such a case, whole object (in .res file) is equivalent to a + // DIALOGEX. It might lead to access violation/segmentation fault in + // resource readers. For example, + // 1 DIALOG 0, 0, 0, 65432 + // STYLE 0xFFFF0001 {} + // would be compiled to a DIALOGEX with 65432 controls. + if ((UsedStyle >> 16) == DialogExMagic) + return createError("16 higher bits of DIALOG resource style cannot be" + " equal to 0xFFFF"); + struct { ulittle32_t Style; ulittle32_t ExtStyle; @@ -486,8 +532,6 @@ writeObject(Prefix); } else { - const uint16_t DialogExMagic = 0xFFFF; - struct { ulittle16_t Version; ulittle16_t Magic; @@ -529,8 +573,21 @@ // Window CLASS field. Not kept here. writeInt(0); - // Window title. There is no title for now, so all we output is '\0'. - writeInt(0); + // Window title or a single word equal to 0. + RETURN_IF_ERROR(writeCString(ObjectData.Caption)); + + // If there *is* a window font declared, output its data. + auto &Font = ObjectData.Font; + if (Font) { + writeInt(Font->Size); + // Additional description occurs only in DIALOGEX. + if (Res->IsExtended) { + writeInt(Font->Weight); + writeInt(Font->IsItalic); + writeInt(Font->Charset); + } + RETURN_IF_ERROR(writeCString(Font->Typeface)); + } auto handleCtlError = [&](Error &&Err, const Control &Ctl) -> Error { if (!Err) Index: llvm/tools/llvm-rc/ResourceScriptParser.h =================================================================== --- llvm/tools/llvm-rc/ResourceScriptParser.h +++ llvm/tools/llvm-rc/ResourceScriptParser.h @@ -124,12 +124,14 @@ // // Ref (to the list of all optional statements): // msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx + enum class OptStmtType { BasicStmt, DialogStmt, DialogExStmt }; + Expected - parseOptionalStatements(bool UseExtendedStatements = false); + parseOptionalStatements(OptStmtType StmtsType = OptStmtType::BasicStmt); // Read a single optional statement. Expected> - parseSingleOptionalStatement(bool UseExtendedStatements = false); + parseSingleOptionalStatement(OptStmtType StmtsType = OptStmtType::BasicStmt); // Top-level resource parsers. ParseType parseLanguageResource(); @@ -163,7 +165,7 @@ ParseOptionType parseCharacteristicsStmt(); ParseOptionType parseVersionStmt(); ParseOptionType parseCaptionStmt(); - ParseOptionType parseFontStmt(); + ParseOptionType parseFontStmt(OptStmtType DialogType); ParseOptionType parseStyleStmt(); // Raises an error. If IsAlreadyRead = false (default), this complains about Index: llvm/tools/llvm-rc/ResourceScriptParser.cpp =================================================================== --- llvm/tools/llvm-rc/ResourceScriptParser.cpp +++ llvm/tools/llvm-rc/ResourceScriptParser.cpp @@ -320,13 +320,13 @@ return Result; } -// As for now, we ignore the extended set of statements. -Expected RCParser::parseOptionalStatements(bool IsExtended) { +Expected +RCParser::parseOptionalStatements(OptStmtType StmtsType) { OptionalStmtList Result; // The last statement is always followed by the start of the block. while (!isNextTokenKind(Kind::BlockBegin)) { - ASSIGN_OR_RETURN(SingleParse, parseSingleOptionalStatement(IsExtended)); + ASSIGN_OR_RETURN(SingleParse, parseSingleOptionalStatement(StmtsType)); Result.addStmt(std::move(*SingleParse)); } @@ -334,7 +334,7 @@ } Expected> -RCParser::parseSingleOptionalStatement(bool IsExtended) { +RCParser::parseSingleOptionalStatement(OptStmtType StmtsType) { ASSIGN_OR_RETURN(TypeToken, readIdentifier()); if (TypeToken->equals_lower("CHARACTERISTICS")) return parseCharacteristicsStmt(); @@ -343,11 +343,11 @@ if (TypeToken->equals_lower("VERSION")) return parseVersionStmt(); - if (IsExtended) { + if (StmtsType != OptStmtType::BasicStmt) { if (TypeToken->equals_lower("CAPTION")) return parseCaptionStmt(); if (TypeToken->equals_lower("FONT")) - return parseFontStmt(); + return parseFontStmt(StmtsType); if (TypeToken->equals_lower("STYLE")) return parseStyleStmt(); } @@ -400,8 +400,9 @@ HelpID = *HelpIDResult; } - ASSIGN_OR_RETURN(OptStatements, - parseOptionalStatements(/*UseExtendedStmts = */ true)); + ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements( + IsExtended ? OptStmtType::DialogExStmt + : OptStmtType::DialogStmt)); assert(isNextTokenKind(Kind::BlockBegin) && "parseOptionalStatements, when successful, halts on BlockBegin."); @@ -664,11 +665,30 @@ return make_unique(*Arg); } -RCParser::ParseOptionType RCParser::parseFontStmt() { +RCParser::ParseOptionType RCParser::parseFontStmt(OptStmtType DialogType) { + assert(DialogType != OptStmtType::BasicStmt); + ASSIGN_OR_RETURN(SizeResult, readInt()); RETURN_IF_ERROR(consumeType(Kind::Comma)); ASSIGN_OR_RETURN(NameResult, readString()); - return make_unique(*SizeResult, *NameResult); + + // Default values for the optional arguments. + uint32_t FontWeight = 0; + bool FontItalic = false; + uint32_t FontCharset = 1; + if (DialogType == OptStmtType::DialogExStmt) { + if (consumeOptionalType(Kind::Comma)) { + ASSIGN_OR_RETURN(Args, readIntsWithCommas(/* min = */ 0, /* max = */ 3)); + if (Args->size() >= 1) + FontWeight = (*Args)[0]; + if (Args->size() >= 2) + FontItalic = (*Args)[1] != 0; + if (Args->size() >= 3) + FontCharset = (*Args)[2]; + } + } + return make_unique(*SizeResult, *NameResult, FontWeight, FontItalic, + FontCharset); } RCParser::ParseOptionType RCParser::parseStyleStmt() { Index: llvm/tools/llvm-rc/ResourceScriptStmt.h =================================================================== --- llvm/tools/llvm-rc/ResourceScriptStmt.h +++ llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -668,11 +668,13 @@ // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx class CaptionStmt : public OptionalStmt { +public: StringRef Value; -public: CaptionStmt(StringRef Caption) : Value(Caption) {} raw_ostream &log(raw_ostream &) const override; + Twine getResourceTypeName() const override { return "CAPTION"; } + Error visit(Visitor *V) const override { return V->visitCaptionStmt(this); } }; // FONT optional statement. @@ -682,24 +684,31 @@ // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx class FontStmt : public OptionalStmt { - uint32_t Size; - StringRef Typeface; - public: - FontStmt(uint32_t FontSize, StringRef FontName) - : Size(FontSize), Typeface(FontName) {} + uint32_t Size, Weight, Charset; + StringRef Name; + bool Italic; + + FontStmt(uint32_t FontSize, StringRef FontName, uint32_t FontWeight, + bool FontItalic, uint32_t FontCharset) + : Size(FontSize), Weight(FontWeight), Charset(FontCharset), + Name(FontName), Italic(FontItalic) {} raw_ostream &log(raw_ostream &) const override; + Twine getResourceTypeName() const override { return "FONT"; } + Error visit(Visitor *V) const override { return V->visitFontStmt(this); } }; // STYLE optional statement. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx class StyleStmt : public OptionalStmt { +public: uint32_t Value; -public: StyleStmt(uint32_t Style) : Value(Style) {} raw_ostream &log(raw_ostream &) const override; + Twine getResourceTypeName() const override { return "STYLE"; } + Error visit(Visitor *V) const override { return V->visitStyleStmt(this); } }; } // namespace rc Index: llvm/tools/llvm-rc/ResourceScriptStmt.cpp =================================================================== --- llvm/tools/llvm-rc/ResourceScriptStmt.cpp +++ llvm/tools/llvm-rc/ResourceScriptStmt.cpp @@ -247,7 +247,11 @@ } raw_ostream &FontStmt::log(raw_ostream &OS) const { - return OS << "Font: size = " << Size << ", face = " << Typeface << "\n"; + OS << "Font: size = " << Size << ", face = " << Name + << ", weight = " << Weight; + if (Italic) + OS << ", italic"; + return OS << ", charset = " << Charset << "\n"; } raw_ostream &StyleStmt::log(raw_ostream &OS) const { Index: llvm/tools/llvm-rc/ResourceVisitor.h =================================================================== --- llvm/tools/llvm-rc/ResourceVisitor.h +++ llvm/tools/llvm-rc/ResourceVisitor.h @@ -21,8 +21,11 @@ class RCResource; +class CaptionStmt; class CharacteristicsStmt; +class FontStmt; class LanguageResource; +class StyleStmt; class VersionStmt; class Visitor { @@ -33,8 +36,11 @@ virtual Error visitHTMLResource(const RCResource *) = 0; virtual Error visitMenuResource(const RCResource *) = 0; + virtual Error visitCaptionStmt(const CaptionStmt *) = 0; virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0; + virtual Error visitFontStmt(const FontStmt *) = 0; virtual Error visitLanguageStmt(const LanguageResource *) = 0; + virtual Error visitStyleStmt(const StyleStmt *) = 0; virtual Error visitVersionStmt(const VersionStmt *) = 0; virtual ~Visitor() {}