@@ -13,7 +13,7 @@ import func POSIX.getenv
13
13
14
14
enum PkgConfigError : ErrorProtocol {
15
15
case CouldNotFindConfigFile
16
- case ParsingError
16
+ case ParsingError( String )
17
17
}
18
18
19
19
struct PkgConfig {
@@ -22,7 +22,6 @@ struct PkgConfig {
22
22
" /usr/lib/pkgconfig " ,
23
23
" /usr/share/pkgconfig " ,
24
24
]
25
-
26
25
let name : String
27
26
let pcFile : String
28
27
let cFlags : [ String ]
@@ -86,23 +85,46 @@ struct PkgConfigParser {
86
85
}
87
86
88
87
mutating func parse( ) throws {
88
+
89
+ func removeComment( line: String ) -> String {
90
+ if let commentIndex = line. characters. index ( of: " # " ) {
91
+ return line [ line. characters. startIndex..< commentIndex]
92
+ }
93
+ return line
94
+ }
95
+
89
96
let file = File ( path: self . pcFile)
90
97
for line in try file. enumerate ( ) {
91
- if !line. characters. contains ( " : " ) && line. characters. contains ( " = " ) {
92
- let equalsIndex = line. characters. index ( of: " = " ) !
98
+ // Ignore any commented line.
99
+ if line. hasPrefix ( " # " ) || line. isEmpty { continue }
100
+ // Remove any trailing comment from the line.
101
+ let line = removeComment ( line: line)
102
+
103
+ if let colonIndex = line. characters. index ( of: " : " ) where line [ colonIndex. successor ( ) ] == " " {
104
+ // Found a key-value pair.
105
+ try parseKeyValue ( line: line)
106
+ } else if let equalsIndex = line. characters. index ( of: " = " ) {
107
+ // Found a variable.
93
108
let name = line [ line. startIndex..< equalsIndex]
94
109
let value = line [ equalsIndex. successor ( ) ..< line. endIndex]
95
110
variables [ name] = try resolveVariables ( value)
96
- } else if line. hasPrefix ( " Requires: " ) {
97
- dependencies = try parseDependencies ( value ( line: line) )
98
- } else if line. hasPrefix ( " Libs: " ) {
99
- libs = try resolveVariables ( value ( line: line) ) . chomp ( )
100
- } else if line. hasPrefix ( " Cflags: " ) {
101
- cFlags = try resolveVariables ( value ( line: line) ) . chomp ( )
111
+ } else {
112
+ // Unexpected thing in the pc file, abort.
113
+ throw PkgConfigError . ParsingError ( " Unexpecting line: \( line) in \( pcFile) " )
102
114
}
103
115
}
104
116
}
105
117
118
+ private mutating func parseKeyValue( line: String ) throws {
119
+ if line. hasPrefix ( " Requires: " ) {
120
+ dependencies = try parseDependencies ( value ( line: line) )
121
+ } else if line. hasPrefix ( " Libs: " ) {
122
+ libs = try resolveVariables ( value ( line: line) ) . chomp ( )
123
+ } else if line. hasPrefix ( " Cflags: " ) {
124
+ cFlags = try resolveVariables ( value ( line: line) ) . chomp ( )
125
+ }
126
+ }
127
+
106
128
/// Parses `Requires: ` string into array of dependencies.
107
129
/// The dependecy string has seperator which can be (multiple) space or a comma.
108
130
/// Additionally each there can be an optional version constaint to a dependency.
@@ -112,7 +134,7 @@ struct PkgConfigParser {
112
134
113
135
// Look at a char at an index if present.
114
136
func peek( idx: Int ) -> Character ? {
115
- guard idx <= depString. characters. count else { return nil }
137
+ guard idx <= depString. characters. count - 1 else { return nil }
116
138
return depString. characters [ depString. characters. startIndex. advanced ( by: idx) ]
117
139
}
118
140
@@ -133,16 +155,20 @@ struct PkgConfigParser {
133
155
token += String ( char)
134
156
}
135
157
}
158
+ // Append the last collected token if present.
159
+ if !token. isEmpty { tokens += [ token] }
136
160
return tokens
137
161
}
138
-
162
+
139
163
var deps = [ String] ( )
140
164
var it = tokenize ( ) . makeIterator ( )
141
165
while let arg = it. next ( ) {
142
166
// If we encounter an operator then we need to skip the next token.
143
167
if operators. contains ( arg) {
144
168
// We should have a version number next, skip.
145
- guard let _ = it. next ( ) else { throw PkgConfigError . ParsingError }
169
+ guard let _ = it. next ( ) else {
170
+ throw PkgConfigError . ParsingError ( " Expected version number after \( deps. last) \( arg) in \" \( depString) \" in \( pcFile) " )
171
+ }
146
172
} else {
147
173
// Otherwise it is a dependency.
148
174
deps. append ( arg)
@@ -174,7 +200,9 @@ struct PkgConfigParser {
174
200
if let variable = findVariable ( fragment) {
175
201
// Append the contents before the variable.
176
202
result += fragment [ fragment. characters. startIndex..< variable. startIndex]
177
- guard let variableValue = variables [ variable. name] else { throw PkgConfigError . ParsingError }
203
+ guard let variableValue = variables [ variable. name] else {
204
+ throw PkgConfigError . ParsingError ( " Expected variable in \( pcFile) " )
205
+ }
178
206
// Append the value of the variable.
179
207
result += variableValue
180
208
// Update the fragment with post variable string.
0 commit comments