@@ -58,6 +58,16 @@ pub fn runAndCompare(self: *CheckObjectStep) *std.Build.RunStep {
5858 return run ;
5959}
6060
61+ const SearchPhrase = struct {
62+ string : []const u8 ,
63+ file_source : ? std.Build.FileSource = null ,
64+
65+ fn resolve (phrase : SearchPhrase , b : * std.Build , step : * Step ) []const u8 {
66+ const file_source = phrase .file_source orelse return phrase .string ;
67+ return b .fmt ("{s} {s}" , .{ phrase .string , file_source .getPath2 (b , step ) });
68+ }
69+ };
70+
6171/// There two types of actions currently suported:
6272/// * `.match` - is the main building block of standard matchers with optional eat-all token `{*}`
6373/// and extractors by name such as `{n_value}`. Please note this action is very simplistic in nature
@@ -72,7 +82,7 @@ pub fn runAndCompare(self: *CheckObjectStep) *std.Build.RunStep {
7282/// they could then be added with this simple program `vmaddr entryoff +`.
7383const Action = struct {
7484 tag : enum { match , not_present , compute_cmp },
75- phrase : [] const u8 ,
85+ phrase : SearchPhrase ,
7686 expected : ? ComputeCompareExpected = null ,
7787
7888 /// Will return true if the `phrase` was found in the `haystack`.
@@ -83,12 +93,18 @@ const Action = struct {
8393 /// and save under `vmaddr` global name (see `global_vars` param)
8494 /// name {*}libobjc{*}.dylib => will match `name` followed by a token which contains `libobjc` and `.dylib`
8595 /// in that order with other letters in between
86- fn match (act : Action , haystack : []const u8 , global_vars : anytype ) ! bool {
96+ fn match (
97+ act : Action ,
98+ b : * std.Build ,
99+ step : * Step ,
100+ haystack : []const u8 ,
101+ global_vars : anytype ,
102+ ) ! bool {
87103 assert (act .tag == .match or act .tag == .not_present );
88-
104+ const phrase = act . phrase . resolve ( b , step );
89105 var candidate_var : ? struct { name : []const u8 , value : u64 } = null ;
90106 var hay_it = mem .tokenize (u8 , mem .trim (u8 , haystack , " " ), " " );
91- var needle_it = mem .tokenize (u8 , mem .trim (u8 , act . phrase , " " ), " " );
107+ var needle_it = mem .tokenize (u8 , mem .trim (u8 , phrase , " " ), " " );
92108
93109 while (needle_it .next ()) | needle_tok | {
94110 const hay_tok = hay_it .next () orelse return false ;
@@ -133,12 +149,13 @@ const Action = struct {
133149 /// Will return true if the `phrase` is correctly parsed into an RPN program and
134150 /// its reduced, computed value compares using `op` with the expected value, either
135151 /// a literal or another extracted variable.
136- fn computeCmp (act : Action , step : * Step , global_vars : anytype ) ! bool {
152+ fn computeCmp (act : Action , b : * std.Build , step : * Step , global_vars : anytype ) ! bool {
137153 const gpa = step .owner .allocator ;
154+ const phrase = act .phrase .resolve (b , step );
138155 var op_stack = std .ArrayList (enum { add , sub , mod , mul }).init (gpa );
139156 var values = std .ArrayList (u64 ).init (gpa );
140157
141- var it = mem .tokenize (u8 , act . phrase , " " );
158+ var it = mem .tokenize (u8 , phrase , " " );
142159 while (it .next ()) | next | {
143160 if (mem .eql (u8 , next , "+" )) {
144161 try op_stack .append (.add );
@@ -225,43 +242,41 @@ const ComputeCompareExpected = struct {
225242};
226243
227244const Check = struct {
228- builder : * std.Build ,
229245 actions : std .ArrayList (Action ),
230246
231- fn create (b : * std.Build ) Check {
247+ fn create (allocator : Allocator ) Check {
232248 return .{
233- .builder = b ,
234- .actions = std .ArrayList (Action ).init (b .allocator ),
249+ .actions = std .ArrayList (Action ).init (allocator ),
235250 };
236251 }
237252
238- fn match (self : * Check , phrase : [] const u8 ) void {
253+ fn match (self : * Check , phrase : SearchPhrase ) void {
239254 self .actions .append (.{
240255 .tag = .match ,
241- .phrase = self . builder . dupe ( phrase ) ,
256+ .phrase = phrase ,
242257 }) catch @panic ("OOM" );
243258 }
244259
245- fn notPresent (self : * Check , phrase : [] const u8 ) void {
260+ fn notPresent (self : * Check , phrase : SearchPhrase ) void {
246261 self .actions .append (.{
247262 .tag = .not_present ,
248- .phrase = self . builder . dupe ( phrase ) ,
263+ .phrase = phrase ,
249264 }) catch @panic ("OOM" );
250265 }
251266
252- fn computeCmp (self : * Check , phrase : [] const u8 , expected : ComputeCompareExpected ) void {
267+ fn computeCmp (self : * Check , phrase : SearchPhrase , expected : ComputeCompareExpected ) void {
253268 self .actions .append (.{
254269 .tag = .compute_cmp ,
255- .phrase = self . builder . dupe ( phrase ) ,
270+ .phrase = phrase ,
256271 .expected = expected ,
257272 }) catch @panic ("OOM" );
258273 }
259274};
260275
261276/// Creates a new sequence of actions with `phrase` as the first anchor searched phrase.
262277pub fn checkStart (self : * CheckObjectStep , phrase : []const u8 ) void {
263- var new_check = Check .create (self .step .owner );
264- new_check .match (phrase );
278+ var new_check = Check .create (self .step .owner . allocator );
279+ new_check .match (.{ . string = self . step . owner . dupe ( phrase ) } );
265280 self .checks .append (new_check ) catch @panic ("OOM" );
266281}
267282
@@ -270,7 +285,19 @@ pub fn checkStart(self: *CheckObjectStep, phrase: []const u8) void {
270285pub fn checkNext (self : * CheckObjectStep , phrase : []const u8 ) void {
271286 assert (self .checks .items .len > 0 );
272287 const last = & self .checks .items [self .checks .items .len - 1 ];
273- last .match (phrase );
288+ last .match (.{ .string = self .step .owner .dupe (phrase ) });
289+ }
290+
291+ /// Like `checkNext()` but takes an additional argument `FileSource` which will be
292+ /// resolved to a full search query in `make()`.
293+ pub fn checkNextFileSource (
294+ self : * CheckObjectStep ,
295+ phrase : []const u8 ,
296+ file_source : std.Build.FileSource ,
297+ ) void {
298+ assert (self .checks .items .len > 0 );
299+ const last = & self .checks .items [self .checks .items .len - 1 ];
300+ last .match (.{ .string = self .step .owner .dupe (phrase ), .file_source = file_source });
274301}
275302
276303/// Adds another searched phrase to the latest created Check with `CheckObjectStep.checkStart(...)`
@@ -279,7 +306,7 @@ pub fn checkNext(self: *CheckObjectStep, phrase: []const u8) void {
279306pub fn checkNotPresent (self : * CheckObjectStep , phrase : []const u8 ) void {
280307 assert (self .checks .items .len > 0 );
281308 const last = & self .checks .items [self .checks .items .len - 1 ];
282- last .notPresent (phrase );
309+ last .notPresent (.{ . string = self . step . owner . dupe ( phrase ) } );
283310}
284311
285312/// Creates a new check checking specifically symbol table parsed and dumped from the object
@@ -302,8 +329,8 @@ pub fn checkComputeCompare(
302329 program : []const u8 ,
303330 expected : ComputeCompareExpected ,
304331) void {
305- var new_check = Check .create (self .step .owner );
306- new_check .computeCmp (program , expected );
332+ var new_check = Check .create (self .step .owner . allocator );
333+ new_check .computeCmp (.{ . string = self . step . owner . dupe ( program ) } , expected );
307334 self .checks .append (new_check ) catch @panic ("OOM" );
308335}
309336
@@ -343,7 +370,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
343370 switch (act .tag ) {
344371 .match = > {
345372 while (it .next ()) | line | {
346- if (try act .match (line , & vars )) break ;
373+ if (try act .match (b , step , line , & vars )) break ;
347374 } else {
348375 return step .fail (
349376 \\
@@ -352,25 +379,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
352379 \\========= but parsed file does not contain it: =======
353380 \\{s}
354381 \\======================================================
355- , .{ act .phrase , output });
382+ , .{ act .phrase . resolve ( b , step ) , output });
356383 }
357384 },
358385 .not_present = > {
359386 while (it .next ()) | line | {
360- if (try act .match (line , & vars )) {
387+ if (try act .match (b , step , line , & vars )) {
361388 return step .fail (
362389 \\
363390 \\========= expected not to find: ===================
364391 \\{s}
365392 \\========= but parsed file does contain it: ========
366393 \\{s}
367394 \\===================================================
368- , .{ act .phrase , output });
395+ , .{ act .phrase . resolve ( b , step ) , output });
369396 }
370397 }
371398 },
372399 .compute_cmp = > {
373- const res = act .computeCmp (step , vars ) catch | err | switch (err ) {
400+ const res = act .computeCmp (b , step , vars ) catch | err | switch (err ) {
374401 error .UnknownVariable = > {
375402 return step .fail (
376403 \\========= from parsed file: =====================
@@ -388,7 +415,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
388415 \\========= from parsed file: =======================
389416 \\{s}
390417 \\===================================================
391- , .{ act .phrase , act .expected .? , output });
418+ , .{ act .phrase . resolve ( b , step ) , act .expected .? , output });
392419 }
393420 },
394421 }
0 commit comments