[llvm-rc] Add optional serialization support for DIALOG(EX) resources.

This is part 5 of llvm-rc serialization support.

This allows DIALOG and DIALOGEX to serialize if dialog-specific optional
statements are provided. These are (as of now): CAPTION, FONT, and
STYLE.

Notably, FONT statement can take more than two arguments when describing
DIALOGEX resources (as in
msdn.microsoft.com/en-us/library/windows/desktop/aa381013.aspx). I made
some changes to the parser to reflect this fact.

Patch by Marek Sokolowski
Differential Revision: https://reviews.llvm.org/D37864

llvm-svn: 315104
This commit is contained in:
Zachary Turner 2017-10-06 20:51:20 +00:00
parent e9baea8178
commit 420090af89
13 changed files with 597 additions and 28 deletions

View File

@ -61,7 +61,7 @@ LANGUAGE 4, 1
LANGUAGE 1, 2 LANGUAGE 1, 2
CHARACTERISTICS 50 CHARACTERISTICS 50
VERSION 100 VERSION 100
FONT 12, "Arial" FONT 12, "Arial", 500, 1, 13
CAPTION "RC parser dialog" CAPTION "RC parser dialog"
STYLE 0x51234 STYLE 0x51234
BEGIN BEGIN

View File

@ -0,0 +1,4 @@
1 DIALOG 1, 2, 3, 4
FONT 12, "Face", 100, 1, 0
BEGIN
END

View File

@ -0,0 +1,2 @@
1 DIALOG 1, 2, 3, 4
STYLE 0xFFFF0001 {}

View File

@ -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 {}

View File

@ -53,7 +53,7 @@
; PGOOD-NEXT: Option: Language: 1, Sublanguage: 2 ; PGOOD-NEXT: Option: Language: 1, Sublanguage: 2
; PGOOD-NEXT: Option: Characteristics: 50 ; PGOOD-NEXT: Option: Characteristics: 50
; PGOOD-NEXT: Option: Version: 100 ; 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: Caption: "RC parser dialog"
; PGOOD-NEXT: Option: Style: 332340 ; PGOOD-NEXT: Option: Style: 332340
; PGOOD-NEXT: Control (14): LTEXT, title: "Hello world!", loc: (20, 20), size: [50, 50] ; 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" ; 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 ; 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 ; PVERSIONINFO1: llvm-rc: Error parsing file: expected fixed VERSIONINFO statement type, got WEIRDFIXED

View File

@ -132,6 +132,393 @@
; DIALOG-NEXT: ) ; 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 ; 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: llvm-rc: Error in DIALOGEX statement (ID 1):
; CTL-REF-ID-NEXT: Error in CTEXT control (ID 42): ; CTL-REF-ID-NEXT: Error in CTEXT control (ID 42):
; CTL-REF-ID-NEXT: Control reference ID (65536) does not fit in 16 bits. ; 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

View File

@ -224,6 +224,11 @@ Error ResourceFileWriter::visitDialogResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeDialogBody); return writeResource(Res, &ResourceFileWriter::writeDialogBody);
} }
Error ResourceFileWriter::visitCaptionStmt(const CaptionStmt *Stmt) {
ObjectData.Caption = Stmt->Value;
return Error::success();
}
Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) { Error ResourceFileWriter::visitHTMLResource(const RCResource *Res) {
return writeResource(Res, &ResourceFileWriter::writeHTMLBody); return writeResource(Res, &ResourceFileWriter::writeHTMLBody);
} }
@ -238,6 +243,16 @@ Error ResourceFileWriter::visitCharacteristicsStmt(
return Error::success(); return Error::success();
} }
Error ResourceFileWriter::visitFontStmt(const FontStmt *Stmt) {
RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Size, "Font size"));
RETURN_IF_ERROR(checkNumberFits<uint16_t>(Stmt->Weight, "Font weight"));
RETURN_IF_ERROR(checkNumberFits<uint8_t>(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) { Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
RETURN_IF_ERROR(checkNumberFits(Stmt->Lang, 10, "Primary language ID")); RETURN_IF_ERROR(checkNumberFits(Stmt->Lang, 10, "Primary language ID"));
RETURN_IF_ERROR(checkNumberFits(Stmt->SubLang, 6, "Sublanguage ID")); RETURN_IF_ERROR(checkNumberFits(Stmt->SubLang, 6, "Sublanguage ID"));
@ -245,6 +260,11 @@ Error ResourceFileWriter::visitLanguageStmt(const LanguageResource *Stmt) {
return Error::success(); return Error::success();
} }
Error ResourceFileWriter::visitStyleStmt(const StyleStmt *Stmt) {
ObjectData.Style = Stmt->Value;
return Error::success();
}
Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) { Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) {
ObjectData.VersionInfo = Stmt->Value; ObjectData.VersionInfo = Stmt->Value;
return Error::success(); return Error::success();
@ -474,10 +494,36 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
auto *Res = cast<DialogResource>(Base); auto *Res = cast<DialogResource>(Base);
// Default style: WS_POPUP | WS_BORDER | WS_SYSMENU. // 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. // Write DIALOG(EX) header prefix. These are pretty different.
if (!Res->IsExtended) { 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 { struct {
ulittle32_t Style; ulittle32_t Style;
ulittle32_t ExtStyle; ulittle32_t ExtStyle;
@ -486,8 +532,6 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
writeObject(Prefix); writeObject(Prefix);
} else { } else {
const uint16_t DialogExMagic = 0xFFFF;
struct { struct {
ulittle16_t Version; ulittle16_t Version;
ulittle16_t Magic; ulittle16_t Magic;
@ -529,8 +573,21 @@ Error ResourceFileWriter::writeDialogBody(const RCResource *Base) {
// Window CLASS field. Not kept here. // Window CLASS field. Not kept here.
writeInt<uint16_t>(0); writeInt<uint16_t>(0);
// Window title. There is no title for now, so all we output is '\0'. // Window title or a single word equal to 0.
writeInt<uint16_t>(0); RETURN_IF_ERROR(writeCString(ObjectData.Caption));
// If there *is* a window font declared, output its data.
auto &Font = ObjectData.Font;
if (Font) {
writeInt<uint16_t>(Font->Size);
// Additional description occurs only in DIALOGEX.
if (Res->IsExtended) {
writeInt<uint16_t>(Font->Weight);
writeInt<uint8_t>(Font->IsItalic);
writeInt<uint8_t>(Font->Charset);
}
RETURN_IF_ERROR(writeCString(Font->Typeface));
}
auto handleCtlError = [&](Error &&Err, const Control &Ctl) -> Error { auto handleCtlError = [&](Error &&Err, const Control &Ctl) -> Error {
if (!Err) if (!Err)

View File

@ -35,8 +35,11 @@ public:
Error visitHTMLResource(const RCResource *) override; Error visitHTMLResource(const RCResource *) override;
Error visitMenuResource(const RCResource *) override; Error visitMenuResource(const RCResource *) override;
Error visitCaptionStmt(const CaptionStmt *) override;
Error visitCharacteristicsStmt(const CharacteristicsStmt *) override; Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
Error visitFontStmt(const FontStmt *) override;
Error visitLanguageStmt(const LanguageResource *) override; Error visitLanguageStmt(const LanguageResource *) override;
Error visitStyleStmt(const StyleStmt *) override;
Error visitVersionStmt(const VersionStmt *) override; Error visitVersionStmt(const VersionStmt *) override;
struct ObjectInfo { struct ObjectInfo {
@ -44,6 +47,17 @@ public:
uint32_t Characteristics; uint32_t Characteristics;
uint32_t VersionInfo; uint32_t VersionInfo;
Optional<uint32_t> Style;
StringRef Caption;
struct FontInfo {
uint32_t Size;
StringRef Typeface;
uint32_t Weight;
bool IsItalic;
uint32_t Charset;
};
Optional<FontInfo> Font;
ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {} ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
} ObjectData; } ObjectData;

View File

@ -320,13 +320,13 @@ Expected<uint32_t> RCParser::parseFlags(ArrayRef<StringRef> FlagDesc,
return Result; return Result;
} }
// As for now, we ignore the extended set of statements. Expected<OptionalStmtList>
Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) { RCParser::parseOptionalStatements(OptStmtType StmtsType) {
OptionalStmtList Result; OptionalStmtList Result;
// The last statement is always followed by the start of the block. // The last statement is always followed by the start of the block.
while (!isNextTokenKind(Kind::BlockBegin)) { while (!isNextTokenKind(Kind::BlockBegin)) {
ASSIGN_OR_RETURN(SingleParse, parseSingleOptionalStatement(IsExtended)); ASSIGN_OR_RETURN(SingleParse, parseSingleOptionalStatement(StmtsType));
Result.addStmt(std::move(*SingleParse)); Result.addStmt(std::move(*SingleParse));
} }
@ -334,7 +334,7 @@ Expected<OptionalStmtList> RCParser::parseOptionalStatements(bool IsExtended) {
} }
Expected<std::unique_ptr<OptionalStmt>> Expected<std::unique_ptr<OptionalStmt>>
RCParser::parseSingleOptionalStatement(bool IsExtended) { RCParser::parseSingleOptionalStatement(OptStmtType StmtsType) {
ASSIGN_OR_RETURN(TypeToken, readIdentifier()); ASSIGN_OR_RETURN(TypeToken, readIdentifier());
if (TypeToken->equals_lower("CHARACTERISTICS")) if (TypeToken->equals_lower("CHARACTERISTICS"))
return parseCharacteristicsStmt(); return parseCharacteristicsStmt();
@ -343,11 +343,11 @@ RCParser::parseSingleOptionalStatement(bool IsExtended) {
if (TypeToken->equals_lower("VERSION")) if (TypeToken->equals_lower("VERSION"))
return parseVersionStmt(); return parseVersionStmt();
if (IsExtended) { if (StmtsType != OptStmtType::BasicStmt) {
if (TypeToken->equals_lower("CAPTION")) if (TypeToken->equals_lower("CAPTION"))
return parseCaptionStmt(); return parseCaptionStmt();
if (TypeToken->equals_lower("FONT")) if (TypeToken->equals_lower("FONT"))
return parseFontStmt(); return parseFontStmt(StmtsType);
if (TypeToken->equals_lower("STYLE")) if (TypeToken->equals_lower("STYLE"))
return parseStyleStmt(); return parseStyleStmt();
} }
@ -401,8 +401,9 @@ RCParser::ParseType RCParser::parseDialogResource(bool IsExtended) {
HelpID = *HelpIDResult; HelpID = *HelpIDResult;
} }
ASSIGN_OR_RETURN(OptStatements, ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements(
parseOptionalStatements(/*UseExtendedStmts = */ true)); IsExtended ? OptStmtType::DialogExStmt
: OptStmtType::DialogStmt));
assert(isNextTokenKind(Kind::BlockBegin) && assert(isNextTokenKind(Kind::BlockBegin) &&
"parseOptionalStatements, when successful, halts on BlockBegin."); "parseOptionalStatements, when successful, halts on BlockBegin.");
@ -666,11 +667,30 @@ RCParser::ParseOptionType RCParser::parseCaptionStmt() {
return llvm::make_unique<CaptionStmt>(*Arg); return llvm::make_unique<CaptionStmt>(*Arg);
} }
RCParser::ParseOptionType RCParser::parseFontStmt() { RCParser::ParseOptionType RCParser::parseFontStmt(OptStmtType DialogType) {
assert(DialogType != OptStmtType::BasicStmt);
ASSIGN_OR_RETURN(SizeResult, readInt()); ASSIGN_OR_RETURN(SizeResult, readInt());
RETURN_IF_ERROR(consumeType(Kind::Comma)); RETURN_IF_ERROR(consumeType(Kind::Comma));
ASSIGN_OR_RETURN(NameResult, readString()); ASSIGN_OR_RETURN(NameResult, readString());
return llvm::make_unique<FontStmt>(*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 llvm::make_unique<FontStmt>(*SizeResult, *NameResult, FontWeight,
FontItalic, FontCharset);
} }
RCParser::ParseOptionType RCParser::parseStyleStmt() { RCParser::ParseOptionType RCParser::parseStyleStmt() {

View File

@ -124,12 +124,14 @@ private:
// //
// Ref (to the list of all optional statements): // Ref (to the list of all optional statements):
// msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx // msdn.microsoft.com/en-us/library/windows/desktop/aa381002(v=vs.85).aspx
enum class OptStmtType { BasicStmt, DialogStmt, DialogExStmt };
Expected<OptionalStmtList> Expected<OptionalStmtList>
parseOptionalStatements(bool UseExtendedStatements = false); parseOptionalStatements(OptStmtType StmtsType = OptStmtType::BasicStmt);
// Read a single optional statement. // Read a single optional statement.
Expected<std::unique_ptr<OptionalStmt>> Expected<std::unique_ptr<OptionalStmt>>
parseSingleOptionalStatement(bool UseExtendedStatements = false); parseSingleOptionalStatement(OptStmtType StmtsType = OptStmtType::BasicStmt);
// Top-level resource parsers. // Top-level resource parsers.
ParseType parseLanguageResource(); ParseType parseLanguageResource();
@ -163,7 +165,7 @@ private:
ParseOptionType parseCharacteristicsStmt(); ParseOptionType parseCharacteristicsStmt();
ParseOptionType parseVersionStmt(); ParseOptionType parseVersionStmt();
ParseOptionType parseCaptionStmt(); ParseOptionType parseCaptionStmt();
ParseOptionType parseFontStmt(); ParseOptionType parseFontStmt(OptStmtType DialogType);
ParseOptionType parseStyleStmt(); ParseOptionType parseStyleStmt();
// Raises an error. If IsAlreadyRead = false (default), this complains about // Raises an error. If IsAlreadyRead = false (default), this complains about

View File

@ -247,7 +247,11 @@ raw_ostream &CaptionStmt::log(raw_ostream &OS) const {
} }
raw_ostream &FontStmt::log(raw_ostream &OS) const { 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 { raw_ostream &StyleStmt::log(raw_ostream &OS) const {

View File

@ -665,11 +665,13 @@ public:
// //
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380778(v=vs.85).aspx
class CaptionStmt : public OptionalStmt { class CaptionStmt : public OptionalStmt {
public:
StringRef Value; StringRef Value;
public:
CaptionStmt(StringRef Caption) : Value(Caption) {} CaptionStmt(StringRef Caption) : Value(Caption) {}
raw_ostream &log(raw_ostream &) const override; 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. // FONT optional statement.
@ -679,24 +681,31 @@ public:
// //
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381013(v=vs.85).aspx
class FontStmt : public OptionalStmt { class FontStmt : public OptionalStmt {
uint32_t Size;
StringRef Typeface;
public: public:
FontStmt(uint32_t FontSize, StringRef FontName) uint32_t Size, Weight, Charset;
: Size(FontSize), Typeface(FontName) {} 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; 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. // STYLE optional statement.
// //
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381051(v=vs.85).aspx
class StyleStmt : public OptionalStmt { class StyleStmt : public OptionalStmt {
public:
uint32_t Value; uint32_t Value;
public:
StyleStmt(uint32_t Style) : Value(Style) {} StyleStmt(uint32_t Style) : Value(Style) {}
raw_ostream &log(raw_ostream &) const override; 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 } // namespace rc

View File

@ -21,8 +21,11 @@ namespace rc {
class RCResource; class RCResource;
class CaptionStmt;
class CharacteristicsStmt; class CharacteristicsStmt;
class FontStmt;
class LanguageResource; class LanguageResource;
class StyleStmt;
class VersionStmt; class VersionStmt;
class Visitor { class Visitor {
@ -33,8 +36,11 @@ public:
virtual Error visitHTMLResource(const RCResource *) = 0; virtual Error visitHTMLResource(const RCResource *) = 0;
virtual Error visitMenuResource(const RCResource *) = 0; virtual Error visitMenuResource(const RCResource *) = 0;
virtual Error visitCaptionStmt(const CaptionStmt *) = 0;
virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0; virtual Error visitCharacteristicsStmt(const CharacteristicsStmt *) = 0;
virtual Error visitFontStmt(const FontStmt *) = 0;
virtual Error visitLanguageStmt(const LanguageResource *) = 0; virtual Error visitLanguageStmt(const LanguageResource *) = 0;
virtual Error visitStyleStmt(const StyleStmt *) = 0;
virtual Error visitVersionStmt(const VersionStmt *) = 0; virtual Error visitVersionStmt(const VersionStmt *) = 0;
virtual ~Visitor() {} virtual ~Visitor() {}