| ... | ... | @@ -1,14 +1,15 @@ |
| 1 | 1 | const Tokenizer = @This(); |
| 2 | 2 | |
| 3 | | index: usize = 0, |
| 4 | | bytes: []const u8, |
| 5 | | state: State = .lhs, |
| 6 | | |
| 7 | 3 | const std = @import("std"); |
| 4 | const Io = std.Io; |
| 8 | 5 | const testing = std.testing; |
| 9 | 6 | const assert = std.debug.assert; |
| 10 | 7 | const Allocator = std.mem.Allocator; |
| 11 | 8 | |
| 9 | index: usize = 0, |
| 10 | bytes: []const u8, |
| 11 | state: State = .lhs, |
| 12 | |
| 12 | 13 | pub fn next(self: *Tokenizer) ?Token { |
| 13 | 14 | var start = self.index; |
| 14 | 15 | var must_resolve = false; |
| ... | ... | @@ -16,10 +17,7 @@ pub fn next(self: *Tokenizer) ?Token { |
| 16 | 17 | const char = self.bytes[self.index]; |
| 17 | 18 | switch (self.state) { |
| 18 | 19 | .lhs => switch (char) { |
| 19 | | '\t', '\n', '\r', ' ' => { |
| 20 | | // silently ignore whitespace |
| 21 | | self.index += 1; |
| 22 | | }, |
| 20 | '\t', '\n', '\r', ' ' => self.index += 1, // Ignore whitespace. |
| 23 | 21 | else => { |
| 24 | 22 | start = self.index; |
| 25 | 23 | self.state = .target; |
| ... | ... | @@ -79,7 +77,7 @@ pub fn next(self: *Tokenizer) ?Token { |
| 79 | 77 | self.index += 1; |
| 80 | 78 | }, |
| 81 | 79 | else => { |
| 82 | | return errorIllegalChar(.expected_dollar_sign, self.index, char); |
| 80 | return errorIllegalChar(.expected_dollar, self.index, char); |
| 83 | 81 | }, |
| 84 | 82 | }, |
| 85 | 83 | .target_colon => switch (char) { |
| ... | ... | @@ -347,7 +345,7 @@ pub const Token = union(enum) { |
| 347 | 345 | |
| 348 | 346 | invalid_target: IndexAndChar, |
| 349 | 347 | bad_target_escape: IndexAndChar, |
| 350 | | expected_dollar_sign: IndexAndChar, |
| 348 | expected_dollar: IndexAndChar, |
| 351 | 349 | continuation_eol: IndexAndChar, |
| 352 | 350 | incomplete_escape: IndexAndChar, |
| 353 | 351 | expected_colon: IndexAndChar, |
| ... | ... | @@ -429,48 +427,23 @@ pub const Token = union(enum) { |
| 429 | 427 | } |
| 430 | 428 | } |
| 431 | 429 | |
| 432 | | pub fn printError(self: Token, gpa: Allocator, list: *std.ArrayList(u8)) error{OutOfMemory}!void { |
| 433 | | switch (self) { |
| 434 | | .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error |
| 435 | | .incomplete_quoted_prerequisite, |
| 436 | | .incomplete_target, |
| 437 | | => |index_and_bytes| { |
| 438 | | try list.print(gpa, "{s} '", .{self.errStr()}); |
| 439 | | if (self == .incomplete_target) { |
| 440 | | const tmp = Token{ .target_must_resolve = index_and_bytes.bytes }; |
| 441 | | try tmp.resolve(gpa, list); |
| 442 | | } else { |
| 443 | | try printCharValues(gpa, list, index_and_bytes.bytes); |
| 444 | | } |
| 445 | | try list.print(gpa, "' at position {d}", .{index_and_bytes.index}); |
| 446 | | }, |
| 430 | pub fn format(token: Token, w: *Io.Writer) Io.Writer.Error!void { |
| 431 | switch (token) { |
| 432 | .target, .target_must_resolve, .prereq, .prereq_must_resolve => return w.writeAll(@tagName(token)), |
| 433 | .incomplete_quoted_prerequisite, .incomplete_target => |info| return w.print("{t} {q} at position {d}", .{ |
| 434 | token, info.bytes, info.index, |
| 435 | }), |
| 447 | 436 | .invalid_target, |
| 448 | 437 | .bad_target_escape, |
| 449 | | .expected_dollar_sign, |
| 438 | .expected_dollar, |
| 450 | 439 | .continuation_eol, |
| 451 | 440 | .incomplete_escape, |
| 452 | 441 | .expected_colon, |
| 453 | | => |index_and_char| { |
| 454 | | try list.appendSlice(gpa, "illegal char "); |
| 455 | | try printUnderstandableChar(gpa, list, index_and_char.char); |
| 456 | | try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() }); |
| 457 | | }, |
| 442 | => |info| return w.print("illegal char '{f}' at position {d}: {t}", .{ |
| 443 | std.zig.fmtChar(info.char), info.index, token, |
| 444 | }), |
| 458 | 445 | } |
| 459 | 446 | } |
| 460 | | |
| 461 | | fn errStr(self: Token) []const u8 { |
| 462 | | return switch (self) { |
| 463 | | .target, .target_must_resolve, .prereq, .prereq_must_resolve => unreachable, // not an error |
| 464 | | .incomplete_quoted_prerequisite => "incomplete quoted prerequisite", |
| 465 | | .incomplete_target => "incomplete target", |
| 466 | | .invalid_target => "invalid target", |
| 467 | | .bad_target_escape => "bad target escape", |
| 468 | | .expected_dollar_sign => "expecting '$'", |
| 469 | | .continuation_eol => "continuation expecting end-of-line", |
| 470 | | .incomplete_escape => "incomplete escape", |
| 471 | | .expected_colon => "expecting ':'", |
| 472 | | }; |
| 473 | | } |
| 474 | 447 | }; |
| 475 | 448 | |
| 476 | 449 | test "empty file" { |
| ... | ... | @@ -493,37 +466,37 @@ test "empty colon" { |
| 493 | 466 | } |
| 494 | 467 | |
| 495 | 468 | test "empty target" { |
| 496 | | try depTokenizer("foo.o:", "target = {foo.o}"); |
| 469 | try depTokenizer("foo.o:", "target = {\"foo.o\"}"); |
| 497 | 470 | try depTokenizer( |
| 498 | 471 | \\foo.o: |
| 499 | 472 | \\bar.o: |
| 500 | 473 | \\abcd.o: |
| 501 | 474 | , |
| 502 | | \\target = {foo.o} |
| 503 | | \\target = {bar.o} |
| 504 | | \\target = {abcd.o} |
| 475 | \\target = {"foo.o"} |
| 476 | \\target = {"bar.o"} |
| 477 | \\target = {"abcd.o"} |
| 505 | 478 | ); |
| 506 | 479 | } |
| 507 | 480 | |
| 508 | 481 | test "whitespace empty target" { |
| 509 | | try depTokenizer("\nfoo.o:", "target = {foo.o}"); |
| 510 | | try depTokenizer("\rfoo.o:", "target = {foo.o}"); |
| 511 | | try depTokenizer("\r\nfoo.o:", "target = {foo.o}"); |
| 512 | | try depTokenizer(" foo.o:", "target = {foo.o}"); |
| 482 | try depTokenizer("\nfoo.o:", "target = {\"foo.o\"}"); |
| 483 | try depTokenizer("\rfoo.o:", "target = {\"foo.o\"}"); |
| 484 | try depTokenizer("\r\nfoo.o:", "target = {\"foo.o\"}"); |
| 485 | try depTokenizer(" foo.o:", "target = {\"foo.o\"}"); |
| 513 | 486 | } |
| 514 | 487 | |
| 515 | 488 | test "escape empty target" { |
| 516 | | try depTokenizer("\\ foo.o:", "target = { foo.o}"); |
| 517 | | try depTokenizer("\\#foo.o:", "target = {#foo.o}"); |
| 518 | | try depTokenizer("\\\\foo.o:", "target = {\\foo.o}"); |
| 519 | | try depTokenizer("$$foo.o:", "target = {$foo.o}"); |
| 489 | try depTokenizer("\\ foo.o:", "target = {\" foo.o\"}"); |
| 490 | try depTokenizer("\\#foo.o:", "target = {\"#foo.o\"}"); |
| 491 | try depTokenizer("\\\\foo.o:", "target = {\"\\\\foo.o\"}"); |
| 492 | try depTokenizer("$$foo.o:", "target = {\"$foo.o\"}"); |
| 520 | 493 | } |
| 521 | 494 | |
| 522 | 495 | test "empty target linefeeds" { |
| 523 | 496 | try depTokenizer("\n", ""); |
| 524 | 497 | try depTokenizer("\r\n", ""); |
| 525 | 498 | |
| 526 | | const expect = "target = {foo.o}"; |
| 499 | const expect = "target = {\"foo.o\"}"; |
| 527 | 500 | try depTokenizer( |
| 528 | 501 | \\foo.o: |
| 529 | 502 | , expect); |
| ... | ... | @@ -541,7 +514,7 @@ test "empty target linefeeds" { |
| 541 | 514 | } |
| 542 | 515 | |
| 543 | 516 | test "empty target linefeeds + continuations" { |
| 544 | | const expect = "target = {foo.o}"; |
| 517 | const expect = "target = {\"foo.o\"}"; |
| 545 | 518 | try depTokenizer( |
| 546 | 519 | \\foo.o:\ |
| 547 | 520 | , expect); |
| ... | ... | @@ -559,7 +532,7 @@ test "empty target linefeeds + continuations" { |
| 559 | 532 | } |
| 560 | 533 | |
| 561 | 534 | test "empty target linefeeds + hspace + continuations" { |
| 562 | | const expect = "target = {foo.o}"; |
| 535 | const expect = "target = {\"foo.o\"}"; |
| 563 | 536 | try depTokenizer( |
| 564 | 537 | \\foo.o: \ |
| 565 | 538 | , expect); |
| ... | ... | @@ -577,7 +550,7 @@ test "empty target linefeeds + hspace + continuations" { |
| 577 | 550 | } |
| 578 | 551 | |
| 579 | 552 | test "empty target + hspace + colon" { |
| 580 | | const expect = "target = {foo.o}"; |
| 553 | const expect = "target = {\"foo.o\"}"; |
| 581 | 554 | |
| 582 | 555 | try depTokenizer("foo.o :", expect); |
| 583 | 556 | try depTokenizer("foo.o\t\t\t:", expect); |
| ... | ... | @@ -588,8 +561,8 @@ test "empty target + hspace + colon" { |
| 588 | 561 | |
| 589 | 562 | test "prereq" { |
| 590 | 563 | const expect = |
| 591 | | \\target = {foo.o} |
| 592 | | \\prereq = {foo.c} |
| 564 | \\target = {"foo.o"} |
| 565 | \\prereq = {"foo.c"} |
| 593 | 566 | ; |
| 594 | 567 | try depTokenizer("foo.o: foo.c", expect); |
| 595 | 568 | try depTokenizer( |
| ... | ... | @@ -608,9 +581,9 @@ test "prereq" { |
| 608 | 581 | |
| 609 | 582 | test "prereq continuation" { |
| 610 | 583 | const expect = |
| 611 | | \\target = {foo.o} |
| 612 | | \\prereq = {foo.h} |
| 613 | | \\prereq = {bar.h} |
| 584 | \\target = {"foo.o"} |
| 585 | \\prereq = {"foo.h"} |
| 586 | \\prereq = {"bar.h"} |
| 614 | 587 | ; |
| 615 | 588 | try depTokenizer( |
| 616 | 589 | \\foo.o: foo.h\ |
| ... | ... | @@ -624,19 +597,19 @@ test "prereq continuation" { |
| 624 | 597 | |
| 625 | 598 | test "prereq continuation (CRLF)" { |
| 626 | 599 | const expect = |
| 627 | | \\target = {foo.o} |
| 628 | | \\prereq = {foo.h} |
| 629 | | \\prereq = {bar.h} |
| 600 | \\target = {"foo.o"} |
| 601 | \\prereq = {"foo.h"} |
| 602 | \\prereq = {"bar.h"} |
| 630 | 603 | ; |
| 631 | 604 | try depTokenizer("foo.o: foo.h\\\r\nbar.h", expect); |
| 632 | 605 | } |
| 633 | 606 | |
| 634 | 607 | test "multiple prereqs" { |
| 635 | 608 | const expect = |
| 636 | | \\target = {foo.o} |
| 637 | | \\prereq = {foo.c} |
| 638 | | \\prereq = {foo.h} |
| 639 | | \\prereq = {bar.h} |
| 609 | \\target = {"foo.o"} |
| 610 | \\prereq = {"foo.c"} |
| 611 | \\prereq = {"foo.h"} |
| 612 | \\prereq = {"bar.h"} |
| 640 | 613 | ; |
| 641 | 614 | try depTokenizer("foo.o: foo.c foo.h bar.h", expect); |
| 642 | 615 | try depTokenizer( |
| ... | ... | @@ -680,19 +653,19 @@ test "multiple targets and prereqs" { |
| 680 | 653 | \\ one.h two.h \ |
| 681 | 654 | \\ three.h four.h |
| 682 | 655 | , |
| 683 | | \\target = {foo.o} |
| 684 | | \\prereq = {foo.c} |
| 685 | | \\target = {bar.o} |
| 686 | | \\prereq = {bar.c} |
| 687 | | \\prereq = {a.h} |
| 688 | | \\prereq = {b.h} |
| 689 | | \\prereq = {c.h} |
| 690 | | \\target = {abc.o} |
| 691 | | \\prereq = {abc.c} |
| 692 | | \\prereq = {one.h} |
| 693 | | \\prereq = {two.h} |
| 694 | | \\prereq = {three.h} |
| 695 | | \\prereq = {four.h} |
| 656 | \\target = {"foo.o"} |
| 657 | \\prereq = {"foo.c"} |
| 658 | \\target = {"bar.o"} |
| 659 | \\prereq = {"bar.c"} |
| 660 | \\prereq = {"a.h"} |
| 661 | \\prereq = {"b.h"} |
| 662 | \\prereq = {"c.h"} |
| 663 | \\target = {"abc.o"} |
| 664 | \\prereq = {"abc.c"} |
| 665 | \\prereq = {"one.h"} |
| 666 | \\prereq = {"two.h"} |
| 667 | \\prereq = {"three.h"} |
| 668 | \\prereq = {"four.h"} |
| 696 | 669 | ); |
| 697 | 670 | try depTokenizer( |
| 698 | 671 | \\ascii.o: ascii.c |
| ... | ... | @@ -702,21 +675,21 @@ test "multiple targets and prereqs" { |
| 702 | 675 | \\ macho.c\ |
| 703 | 676 | \\ a.h b.h c.h |
| 704 | 677 | , |
| 705 | | \\target = {ascii.o} |
| 706 | | \\prereq = {ascii.c} |
| 707 | | \\target = {base64.o} |
| 708 | | \\prereq = {base64.c} |
| 709 | | \\prereq = {stdio.h} |
| 710 | | \\target = {elf.o} |
| 711 | | \\prereq = {elf.c} |
| 712 | | \\prereq = {a.h} |
| 713 | | \\prereq = {b.h} |
| 714 | | \\prereq = {c.h} |
| 715 | | \\target = {macho.o} |
| 716 | | \\prereq = {macho.c} |
| 717 | | \\prereq = {a.h} |
| 718 | | \\prereq = {b.h} |
| 719 | | \\prereq = {c.h} |
| 678 | \\target = {"ascii.o"} |
| 679 | \\prereq = {"ascii.c"} |
| 680 | \\target = {"base64.o"} |
| 681 | \\prereq = {"base64.c"} |
| 682 | \\prereq = {"stdio.h"} |
| 683 | \\target = {"elf.o"} |
| 684 | \\prereq = {"elf.c"} |
| 685 | \\prereq = {"a.h"} |
| 686 | \\prereq = {"b.h"} |
| 687 | \\prereq = {"c.h"} |
| 688 | \\target = {"macho.o"} |
| 689 | \\prereq = {"macho.c"} |
| 690 | \\prereq = {"a.h"} |
| 691 | \\prereq = {"b.h"} |
| 692 | \\prereq = {"c.h"} |
| 720 | 693 | ); |
| 721 | 694 | try depTokenizer( |
| 722 | 695 | \\a$$scii.o: ascii.c |
| ... | ... | @@ -726,20 +699,20 @@ test "multiple targets and prereqs" { |
| 726 | 699 | \\ "macho!.c" \ |
| 727 | 700 | \\ a.h b.h c.h |
| 728 | 701 | , |
| 729 | | \\target = {a$scii.o} |
| 730 | | \\prereq = {ascii.c} |
| 731 | | \\target = {\base64.o} |
| 732 | | \\prereq = {\base64.c} |
| 733 | | \\prereq = {s t#dio.h} |
| 734 | | \\target = {e\lf.o} |
| 735 | | \\prereq = {e\lf.c} |
| 736 | | \\prereq = {a.h$$} |
| 737 | | \\prereq = {$$b.h c.h$$} |
| 738 | | \\target = {macho.o} |
| 739 | | \\prereq = {macho!.c} |
| 740 | | \\prereq = {a.h} |
| 741 | | \\prereq = {b.h} |
| 742 | | \\prereq = {c.h} |
| 702 | \\target = {"a$scii.o"} |
| 703 | \\prereq = {"ascii.c"} |
| 704 | \\target = {"\\base64.o"} |
| 705 | \\prereq = {"\\base64.c"} |
| 706 | \\prereq = {"s t#dio.h"} |
| 707 | \\target = {"e\\lf.o"} |
| 708 | \\prereq = {"e\\lf.c"} |
| 709 | \\prereq = {"a.h$$"} |
| 710 | \\prereq = {"$$b.h c.h$$"} |
| 711 | \\target = {"macho.o"} |
| 712 | \\prereq = {"macho!.c"} |
| 713 | \\prereq = {"a.h"} |
| 714 | \\prereq = {"b.h"} |
| 715 | \\prereq = {"c.h"} |
| 743 | 716 | ); |
| 744 | 717 | } |
| 745 | 718 | |
| ... | ... | @@ -750,12 +723,12 @@ test "windows quoted prereqs" { |
| 750 | 723 | \\ "C:\Program Files (x86)\Microsoft Visual Studio\foo1.h" \ |
| 751 | 724 | \\ "C:\Program Files (x86)\Microsoft Visual Studio\foo2.h" |
| 752 | 725 | , |
| 753 | | \\target = {c:\foo.o} |
| 754 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo.c} |
| 755 | | \\target = {c:\foo2.o} |
| 756 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo2.c} |
| 757 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo1.h} |
| 758 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo2.h} |
| 726 | \\target = {"c:\\foo.o"} |
| 727 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\foo.c"} |
| 728 | \\target = {"c:\\foo2.o"} |
| 729 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\foo2.c"} |
| 730 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\foo1.h"} |
| 731 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\foo2.h"} |
| 759 | 732 | ); |
| 760 | 733 | } |
| 761 | 734 | |
| ... | ... | @@ -779,23 +752,23 @@ test "windows mixed prereqs" { |
| 779 | 752 | \\ "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime_string.h" \ |
| 780 | 753 | \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstring.h" |
| 781 | 754 | , |
| 782 | | \\target = {cimport.o} |
| 783 | | \\prereq = {C:\msys64\home\anon\project\zig\master\zig-cache\o\qhvhbUo7GU5iKyQ5mpA8TcQpncCYaQu0wwvr3ybiSTj_Dtqi1Nmcb70kfODJ2Qlg\cimport.h} |
| 784 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\stdio.h} |
| 785 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt.h} |
| 786 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime.h} |
| 787 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\sal.h} |
| 788 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\concurrencysal.h} |
| 789 | | \\prereq = {C:\msys64\opt\zig\lib\zig\include\vadefs.h} |
| 790 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vadefs.h} |
| 791 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstdio.h} |
| 792 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_stdio_config.h} |
| 793 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\string.h} |
| 794 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_memory.h} |
| 795 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_memcpy_s.h} |
| 796 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\errno.h} |
| 797 | | \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime_string.h} |
| 798 | | \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstring.h} |
| 755 | \\target = {"cimport.o"} |
| 756 | \\prereq = {"C:\\msys64\\home\\anon\\project\\zig\\master\\zig-cache\\o\\qhvhbUo7GU5iKyQ5mpA8TcQpncCYaQu0wwvr3ybiSTj_Dtqi1Nmcb70kfODJ2Qlg\\cimport.h"} |
| 757 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\stdio.h"} |
| 758 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\corecrt.h"} |
| 759 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.21.27702\\lib\\x64\\\\..\\..\\include\\vcruntime.h"} |
| 760 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.21.27702\\lib\\x64\\\\..\\..\\include\\sal.h"} |
| 761 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.21.27702\\lib\\x64\\\\..\\..\\include\\concurrencysal.h"} |
| 762 | \\prereq = {"C:\\msys64\\opt\\zig\\lib\\zig\\include\\vadefs.h"} |
| 763 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.21.27702\\lib\\x64\\\\..\\..\\include\\vadefs.h"} |
| 764 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\corecrt_wstdio.h"} |
| 765 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\corecrt_stdio_config.h"} |
| 766 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\string.h"} |
| 767 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\corecrt_memory.h"} |
| 768 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\corecrt_memcpy_s.h"} |
| 769 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\errno.h"} |
| 770 | \\prereq = {"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.21.27702\\lib\\x64\\\\..\\..\\include\\vcruntime_string.h"} |
| 771 | \\prereq = {"C:\\Program Files (x86)\\Windows Kits\\10\\\\Include\\10.0.17763.0\\ucrt\\corecrt_wstring.h"} |
| 799 | 772 | ); |
| 800 | 773 | } |
| 801 | 774 | |
| ... | ... | @@ -810,14 +783,14 @@ test "windows funky targets" { |
| 810 | 783 | \\C:\Users\anon\$$foo.o: |
| 811 | 784 | \\C:\Users\anon\\\ \ \ \ \ foo.o: |
| 812 | 785 | , |
| 813 | | \\target = {C:\Users\anon\foo.o} |
| 814 | | \\target = {C:\Users\anon\foo .o} |
| 815 | | \\target = {C:\Users\anon\foo#.o} |
| 816 | | \\target = {C:\Users\anon\foo$.o} |
| 817 | | \\target = {C:\Users\anon\ foo.o} |
| 818 | | \\target = {C:\Users\anon\#foo.o} |
| 819 | | \\target = {C:\Users\anon\$foo.o} |
| 820 | | \\target = {C:\Users\anon\ foo.o} |
| 786 | \\target = {"C:\\Users\\anon\\foo.o"} |
| 787 | \\target = {"C:\\Users\\anon\\foo .o"} |
| 788 | \\target = {"C:\\Users\\anon\\foo#.o"} |
| 789 | \\target = {"C:\\Users\\anon\\foo$.o"} |
| 790 | \\target = {"C:\\Users\\anon\\ foo.o"} |
| 791 | \\target = {"C:\\Users\\anon\\#foo.o"} |
| 792 | \\target = {"C:\\Users\\anon\\$foo.o"} |
| 793 | \\target = {"C:\\Users\\anon\\ foo.o"} |
| 821 | 794 | ); |
| 822 | 795 | } |
| 823 | 796 | |
| ... | ... | @@ -837,13 +810,13 @@ test "windows funky prereqs" { |
| 837 | 810 | \\ somedir\\ \\ \c.c\ |
| 838 | 811 | \\ |
| 839 | 812 | , |
| 840 | | \\target = {cimport.o} |
| 841 | | \\prereq = {trailingbackslash\} |
| 842 | | \\prereq = {C:\Users\John Smith\AppData\Local\zig\p\1220d14057af1a9d6dde4643293527bd5ee5099517d655251a066666a4320737ea7c\cimport.c} |
| 843 | | \\prereq = {somedir\ a.c} |
| 844 | | \\prereq = {somedir/ a.c} |
| 845 | | \\prereq = {somedir\ b.c} |
| 846 | | \\prereq = {somedir\ \ \c.c} |
| 813 | \\target = {"cimport.o"} |
| 814 | \\prereq = {"trailingbackslash\\"} |
| 815 | \\prereq = {"C:\\Users\\John Smith\\AppData\\Local\\zig\\p\\1220d14057af1a9d6dde4643293527bd5ee5099517d655251a066666a4320737ea7c\\cimport.c"} |
| 816 | \\prereq = {"somedir\\ a.c"} |
| 817 | \\prereq = {"somedir/ a.c"} |
| 818 | \\prereq = {"somedir\\ b.c"} |
| 819 | \\prereq = {"somedir\\ \\ \\c.c"} |
| 847 | 820 | ); |
| 848 | 821 | } |
| 849 | 822 | |
| ... | ... | @@ -852,171 +825,171 @@ test "windows drive and forward slashes" { |
| 852 | 825 | \\C:/msys64/what/zig-cache\tmp\48ac4d78dd531abd-cxa_thread_atexit.obj: \ |
| 853 | 826 | \\ C:/msys64/opt/zig3/lib/zig/libc/mingw/crt/cxa_thread_atexit.c |
| 854 | 827 | , |
| 855 | | \\target = {C:/msys64/what/zig-cache\tmp\48ac4d78dd531abd-cxa_thread_atexit.obj} |
| 856 | | \\prereq = {C:/msys64/opt/zig3/lib/zig/libc/mingw/crt/cxa_thread_atexit.c} |
| 828 | \\target = {"C:/msys64/what/zig-cache\\tmp\\48ac4d78dd531abd-cxa_thread_atexit.obj"} |
| 829 | \\prereq = {"C:/msys64/opt/zig3/lib/zig/libc/mingw/crt/cxa_thread_atexit.c"} |
| 857 | 830 | ); |
| 858 | 831 | } |
| 859 | 832 | |
| 860 | 833 | test "error incomplete escape - reverse_solidus" { |
| 861 | 834 | try depTokenizer("\\", |
| 862 | | \\ERROR: illegal char '\' at position 0: incomplete escape |
| 835 | \\ERROR: illegal char '\\' at position 0: incomplete_escape |
| 863 | 836 | ); |
| 864 | 837 | try depTokenizer("\t\\", |
| 865 | | \\ERROR: illegal char '\' at position 1: incomplete escape |
| 838 | \\ERROR: illegal char '\\' at position 1: incomplete_escape |
| 866 | 839 | ); |
| 867 | 840 | try depTokenizer("\n\\", |
| 868 | | \\ERROR: illegal char '\' at position 1: incomplete escape |
| 841 | \\ERROR: illegal char '\\' at position 1: incomplete_escape |
| 869 | 842 | ); |
| 870 | 843 | try depTokenizer("\r\\", |
| 871 | | \\ERROR: illegal char '\' at position 1: incomplete escape |
| 844 | \\ERROR: illegal char '\\' at position 1: incomplete_escape |
| 872 | 845 | ); |
| 873 | 846 | try depTokenizer("\r\n\\", |
| 874 | | \\ERROR: illegal char '\' at position 2: incomplete escape |
| 847 | \\ERROR: illegal char '\\' at position 2: incomplete_escape |
| 875 | 848 | ); |
| 876 | 849 | try depTokenizer(" \\", |
| 877 | | \\ERROR: illegal char '\' at position 1: incomplete escape |
| 850 | \\ERROR: illegal char '\\' at position 1: incomplete_escape |
| 878 | 851 | ); |
| 879 | 852 | } |
| 880 | 853 | |
| 881 | 854 | test "error incomplete escape - dollar_sign" { |
| 882 | 855 | try depTokenizer("$", |
| 883 | | \\ERROR: illegal char '$' at position 0: incomplete escape |
| 856 | \\ERROR: illegal char '$' at position 0: incomplete_escape |
| 884 | 857 | ); |
| 885 | 858 | try depTokenizer("\t$", |
| 886 | | \\ERROR: illegal char '$' at position 1: incomplete escape |
| 859 | \\ERROR: illegal char '$' at position 1: incomplete_escape |
| 887 | 860 | ); |
| 888 | 861 | try depTokenizer("\n$", |
| 889 | | \\ERROR: illegal char '$' at position 1: incomplete escape |
| 862 | \\ERROR: illegal char '$' at position 1: incomplete_escape |
| 890 | 863 | ); |
| 891 | 864 | try depTokenizer("\r$", |
| 892 | | \\ERROR: illegal char '$' at position 1: incomplete escape |
| 865 | \\ERROR: illegal char '$' at position 1: incomplete_escape |
| 893 | 866 | ); |
| 894 | 867 | try depTokenizer("\r\n$", |
| 895 | | \\ERROR: illegal char '$' at position 2: incomplete escape |
| 868 | \\ERROR: illegal char '$' at position 2: incomplete_escape |
| 896 | 869 | ); |
| 897 | 870 | try depTokenizer(" $", |
| 898 | | \\ERROR: illegal char '$' at position 1: incomplete escape |
| 871 | \\ERROR: illegal char '$' at position 1: incomplete_escape |
| 899 | 872 | ); |
| 900 | 873 | } |
| 901 | 874 | |
| 902 | 875 | test "error incomplete target" { |
| 903 | 876 | try depTokenizer("foo.o", |
| 904 | | \\ERROR: incomplete target 'foo.o' at position 0 |
| 877 | \\ERROR: incomplete_target "foo.o" at position 0 |
| 905 | 878 | ); |
| 906 | 879 | try depTokenizer("\tfoo.o", |
| 907 | | \\ERROR: incomplete target 'foo.o' at position 1 |
| 880 | \\ERROR: incomplete_target "foo.o" at position 1 |
| 908 | 881 | ); |
| 909 | 882 | try depTokenizer("\nfoo.o", |
| 910 | | \\ERROR: incomplete target 'foo.o' at position 1 |
| 883 | \\ERROR: incomplete_target "foo.o" at position 1 |
| 911 | 884 | ); |
| 912 | 885 | try depTokenizer("\rfoo.o", |
| 913 | | \\ERROR: incomplete target 'foo.o' at position 1 |
| 886 | \\ERROR: incomplete_target "foo.o" at position 1 |
| 914 | 887 | ); |
| 915 | 888 | try depTokenizer("\r\nfoo.o", |
| 916 | | \\ERROR: incomplete target 'foo.o' at position 2 |
| 889 | \\ERROR: incomplete_target "foo.o" at position 2 |
| 917 | 890 | ); |
| 918 | 891 | try depTokenizer(" foo.o", |
| 919 | | \\ERROR: incomplete target 'foo.o' at position 1 |
| 892 | \\ERROR: incomplete_target "foo.o" at position 1 |
| 920 | 893 | ); |
| 921 | 894 | |
| 922 | 895 | try depTokenizer("\\ foo.o", |
| 923 | | \\ERROR: incomplete target ' foo.o' at position 0 |
| 896 | \\ERROR: incomplete_target "\\ foo.o" at position 0 |
| 924 | 897 | ); |
| 925 | 898 | try depTokenizer("\\#foo.o", |
| 926 | | \\ERROR: incomplete target '#foo.o' at position 0 |
| 899 | \\ERROR: incomplete_target "\\#foo.o" at position 0 |
| 927 | 900 | ); |
| 928 | 901 | try depTokenizer("\\\\foo.o", |
| 929 | | \\ERROR: incomplete target '\foo.o' at position 0 |
| 902 | \\ERROR: incomplete_target "\\\\foo.o" at position 0 |
| 930 | 903 | ); |
| 931 | 904 | try depTokenizer("$$foo.o", |
| 932 | | \\ERROR: incomplete target '$foo.o' at position 0 |
| 905 | \\ERROR: incomplete_target "$$foo.o" at position 0 |
| 933 | 906 | ); |
| 934 | 907 | } |
| 935 | 908 | |
| 936 | 909 | test "error illegal char at position - bad target escape" { |
| 937 | 910 | try depTokenizer("\\\t", |
| 938 | | \\ERROR: illegal char \x09 at position 1: bad target escape |
| 911 | \\ERROR: illegal char '\t' at position 1: bad_target_escape |
| 939 | 912 | ); |
| 940 | 913 | try depTokenizer("\\\n", |
| 941 | | \\ERROR: illegal char \x0A at position 1: bad target escape |
| 914 | \\ERROR: illegal char '\n' at position 1: bad_target_escape |
| 942 | 915 | ); |
| 943 | 916 | try depTokenizer("\\\r", |
| 944 | | \\ERROR: illegal char \x0D at position 1: bad target escape |
| 917 | \\ERROR: illegal char '\r' at position 1: bad_target_escape |
| 945 | 918 | ); |
| 946 | 919 | try depTokenizer("\\\r\n", |
| 947 | | \\ERROR: illegal char \x0D at position 1: bad target escape |
| 920 | \\ERROR: illegal char '\r' at position 1: bad_target_escape |
| 948 | 921 | ); |
| 949 | 922 | } |
| 950 | 923 | |
| 951 | 924 | test "error illegal char at position - expecting dollar_sign" { |
| 952 | 925 | try depTokenizer("$\t", |
| 953 | | \\ERROR: illegal char \x09 at position 1: expecting '$' |
| 926 | \\ERROR: illegal char '\t' at position 1: expected_dollar |
| 954 | 927 | ); |
| 955 | 928 | try depTokenizer("$\n", |
| 956 | | \\ERROR: illegal char \x0A at position 1: expecting '$' |
| 929 | \\ERROR: illegal char '\n' at position 1: expected_dollar |
| 957 | 930 | ); |
| 958 | 931 | try depTokenizer("$\r", |
| 959 | | \\ERROR: illegal char \x0D at position 1: expecting '$' |
| 932 | \\ERROR: illegal char '\r' at position 1: expected_dollar |
| 960 | 933 | ); |
| 961 | 934 | try depTokenizer("$\r\n", |
| 962 | | \\ERROR: illegal char \x0D at position 1: expecting '$' |
| 935 | \\ERROR: illegal char '\r' at position 1: expected_dollar |
| 963 | 936 | ); |
| 964 | 937 | } |
| 965 | 938 | |
| 966 | 939 | test "error illegal char at position - invalid target" { |
| 967 | 940 | try depTokenizer("foo\n.o", |
| 968 | | \\ERROR: illegal char \x0A at position 3: invalid target |
| 941 | \\ERROR: illegal char '\n' at position 3: invalid_target |
| 969 | 942 | ); |
| 970 | 943 | try depTokenizer("foo\r.o", |
| 971 | | \\ERROR: illegal char \x0D at position 3: invalid target |
| 944 | \\ERROR: illegal char '\r' at position 3: invalid_target |
| 972 | 945 | ); |
| 973 | 946 | try depTokenizer("foo\r\n.o", |
| 974 | | \\ERROR: illegal char \x0D at position 3: invalid target |
| 947 | \\ERROR: illegal char '\r' at position 3: invalid_target |
| 975 | 948 | ); |
| 976 | 949 | } |
| 977 | 950 | |
| 978 | 951 | test "error target - continuation expecting end-of-line" { |
| 979 | 952 | try depTokenizer("foo.o: \\\t", |
| 980 | | \\target = {foo.o} |
| 981 | | \\ERROR: illegal char \x09 at position 8: continuation expecting end-of-line |
| 953 | \\target = {"foo.o"} |
| 954 | \\ERROR: illegal char '\t' at position 8: continuation_eol |
| 982 | 955 | ); |
| 983 | 956 | try depTokenizer("foo.o: \\ ", |
| 984 | | \\target = {foo.o} |
| 985 | | \\ERROR: illegal char ' ' at position 8: continuation expecting end-of-line |
| 957 | \\target = {"foo.o"} |
| 958 | \\ERROR: illegal char ' ' at position 8: continuation_eol |
| 986 | 959 | ); |
| 987 | 960 | try depTokenizer("foo.o: \\x", |
| 988 | | \\target = {foo.o} |
| 989 | | \\ERROR: illegal char 'x' at position 8: continuation expecting end-of-line |
| 961 | \\target = {"foo.o"} |
| 962 | \\ERROR: illegal char 'x' at position 8: continuation_eol |
| 990 | 963 | ); |
| 991 | 964 | try depTokenizer("foo.o: \\\x0dx", |
| 992 | | \\target = {foo.o} |
| 993 | | \\ERROR: illegal char 'x' at position 9: continuation expecting end-of-line |
| 965 | \\target = {"foo.o"} |
| 966 | \\ERROR: illegal char 'x' at position 9: continuation_eol |
| 994 | 967 | ); |
| 995 | 968 | } |
| 996 | 969 | |
| 997 | 970 | test "error prereq - continuation expecting end-of-line" { |
| 998 | 971 | try depTokenizer("foo.o: foo.h\\\x0dx", |
| 999 | | \\target = {foo.o} |
| 1000 | | \\ERROR: illegal char 'x' at position 14: continuation expecting end-of-line |
| 972 | \\target = {"foo.o"} |
| 973 | \\ERROR: illegal char 'x' at position 14: continuation_eol |
| 1001 | 974 | ); |
| 1002 | 975 | } |
| 1003 | 976 | |
| 1004 | 977 | test "error illegal char at position - expecting colon" { |
| 1005 | 978 | try depTokenizer("foo\t.o:", |
| 1006 | | \\target = {foo} |
| 1007 | | \\ERROR: illegal char '.' at position 4: expecting ':' |
| 979 | \\target = {"foo"} |
| 980 | \\ERROR: illegal char '.' at position 4: expected_colon |
| 1008 | 981 | ); |
| 1009 | 982 | try depTokenizer("foo .o:", |
| 1010 | | \\target = {foo} |
| 1011 | | \\ERROR: illegal char '.' at position 4: expecting ':' |
| 983 | \\target = {"foo"} |
| 984 | \\ERROR: illegal char '.' at position 4: expected_colon |
| 1012 | 985 | ); |
| 1013 | 986 | try depTokenizer("foo \n.o:", |
| 1014 | | \\target = {foo} |
| 1015 | | \\ERROR: illegal char \x0A at position 4: expecting ':' |
| 987 | \\target = {"foo"} |
| 988 | \\ERROR: illegal char '\n' at position 4: expected_colon |
| 1016 | 989 | ); |
| 1017 | 990 | try depTokenizer("foo.o\t\n:", |
| 1018 | | \\target = {foo.o} |
| 1019 | | \\ERROR: illegal char \x0A at position 6: expecting ':' |
| 991 | \\target = {"foo.o"} |
| 992 | \\ERROR: illegal char '\n' at position 6: expected_colon |
| 1020 | 993 | ); |
| 1021 | 994 | } |
| 1022 | 995 | |
| ... | ... | @@ -1028,70 +1001,35 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void { |
| 1028 | 1001 | |
| 1029 | 1002 | var it: Tokenizer = .{ .bytes = input }; |
| 1030 | 1003 | var buffer: std.ArrayList(u8) = .empty; |
| 1031 | | var resolve_buf: std.ArrayList(u8) = .empty; |
| 1004 | var aux: std.ArrayList(u8) = .empty; |
| 1032 | 1005 | var i: usize = 0; |
| 1033 | 1006 | while (it.next()) |token| { |
| 1034 | 1007 | if (i != 0) try buffer.appendSlice(arena, "\n"); |
| 1035 | 1008 | switch (token) { |
| 1036 | 1009 | .target, .prereq => |bytes| { |
| 1037 | | try buffer.appendSlice(arena, @tagName(token)); |
| 1038 | | try buffer.appendSlice(arena, " = {"); |
| 1039 | | for (bytes) |b| { |
| 1040 | | try buffer.append(arena, printable_char_tab[b]); |
| 1041 | | } |
| 1042 | | try buffer.appendSlice(arena, "}"); |
| 1010 | try buffer.print(arena, "{t} = {{{q}}}", .{ token, bytes }); |
| 1043 | 1011 | }, |
| 1044 | 1012 | .target_must_resolve => { |
| 1045 | 1013 | try buffer.appendSlice(arena, "target = {"); |
| 1046 | | try token.resolve(arena, &resolve_buf); |
| 1047 | | for (resolve_buf.items) |b| { |
| 1048 | | try buffer.append(arena, printable_char_tab[b]); |
| 1049 | | } |
| 1050 | | resolve_buf.items.len = 0; |
| 1014 | aux.clearRetainingCapacity(); |
| 1015 | try token.resolve(arena, &aux); |
| 1016 | try buffer.print(arena, "{q}", .{aux.items}); |
| 1051 | 1017 | try buffer.appendSlice(arena, "}"); |
| 1052 | 1018 | }, |
| 1053 | 1019 | .prereq_must_resolve => { |
| 1054 | 1020 | try buffer.appendSlice(arena, "prereq = {"); |
| 1055 | | try token.resolve(arena, &resolve_buf); |
| 1056 | | for (resolve_buf.items) |b| { |
| 1057 | | try buffer.append(arena, printable_char_tab[b]); |
| 1058 | | } |
| 1059 | | resolve_buf.items.len = 0; |
| 1021 | aux.clearRetainingCapacity(); |
| 1022 | try token.resolve(arena, &aux); |
| 1023 | try buffer.print(arena, "{q}", .{aux.items}); |
| 1060 | 1024 | try buffer.appendSlice(arena, "}"); |
| 1061 | 1025 | }, |
| 1062 | 1026 | else => { |
| 1063 | | try buffer.appendSlice(arena, "ERROR: "); |
| 1064 | | try token.printError(arena, &buffer); |
| 1027 | try buffer.print(arena, "ERROR: {f}", .{token}); |
| 1065 | 1028 | break; |
| 1066 | 1029 | }, |
| 1067 | 1030 | } |
| 1068 | 1031 | i += 1; |
| 1069 | 1032 | } |
| 1070 | 1033 | |
| 1071 | | if (std.mem.eql(u8, expect, buffer.items)) { |
| 1072 | | try testing.expect(true); |
| 1073 | | return; |
| 1074 | | } |
| 1075 | | |
| 1076 | 1034 | try testing.expectEqualStrings(expect, buffer.items); |
| 1077 | 1035 | } |
| 1078 | | |
| 1079 | | fn printCharValues(gpa: Allocator, list: *std.ArrayList(u8), bytes: []const u8) !void { |
| 1080 | | for (bytes) |b| try list.append(gpa, printable_char_tab[b]); |
| 1081 | | } |
| 1082 | | |
| 1083 | | fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayList(u8), char: u8) !void { |
| 1084 | | if (std.ascii.isPrint(char)) { |
| 1085 | | try list.print(gpa, "'{c}'", .{char}); |
| 1086 | | } else { |
| 1087 | | try list.print(gpa, "\\x{X:0>2}", .{char}); |
| 1088 | | } |
| 1089 | | } |
| 1090 | | |
| 1091 | | // zig fmt: off |
| 1092 | | const printable_char_tab: [256]u8 = ( |
| 1093 | | "................................ !\"#$%&'()*+,-./0123456789:;<=>?" ++ |
| 1094 | | "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~." ++ |
| 1095 | | "................................................................" ++ |
| 1096 | | "................................................................" |
| 1097 | | ).*; |