| 1 | #!/usr/bin/perl |
| 2 | |
| 3 | use strict; |
| 4 | use warnings; |
| 5 | |
| 6 | # Parse arguments, a simple state machine for input like: |
| 7 | # |
| 8 | # <file-to-check.adoc> <valid-files-to-link-to> --section=1 git.adoc git-add.adoc [...] --to-lint git-add.adoc a-file.adoc [...] |
| 9 | my %TXT; |
| 10 | my %SECTION; |
| 11 | my $section; |
| 12 | my $lint_these = 0; |
| 13 | my $to_check = shift @ARGV; |
| 14 | for my $arg (@ARGV) { |
| 15 | if (my ($sec) = $arg =~ /^--section=(\d+)$/s) { |
| 16 | $section = $sec; |
| 17 | next; |
| 18 | } |
| 19 | |
| 20 | my ($name) = $arg =~ /^(.*?)\.adoc$/s; |
| 21 | unless (defined $section) { |
| 22 | $TXT{$name} = $arg; |
| 23 | next; |
| 24 | } |
| 25 | |
| 26 | $SECTION{$name} = $section; |
| 27 | } |
| 28 | |
| 29 | my $exit_code = 0; |
| 30 | sub report { |
| 31 | my ($pos, $line, $target, $msg) = @_; |
| 32 | substr($line, $pos) = "' <-- HERE"; |
| 33 | $line =~ s/^\s+//; |
| 34 | print STDERR "$ARGV:$.: error: $target: $msg, shown with 'HERE' below:\n"; |
| 35 | print STDERR "$ARGV:$.:\t'$line\n"; |
| 36 | $exit_code = 1; |
| 37 | } |
| 38 | |
| 39 | @ARGV = sort values %TXT; |
| 40 | die "BUG: No list of valid linkgit:* files given" unless @ARGV; |
| 41 | @ARGV = $to_check; |
| 42 | while (<>) { |
| 43 | my $line = $_; |
| 44 | next if $line =~ /^\s*(ifn?def|endif)::/; |
| 45 | while ($line =~ m/(.{,8})((git[-a-z]+|scalar)\[(\d)*\])/g) { |
| 46 | my $pos = pos $line; |
| 47 | my ($macro, $target, $page, $section) = ($1, $2, $3, $4); |
| 48 | if ( $macro ne "linkgit:" ) { |
| 49 | report($pos, $line, $target, "linkgit: macro expected"); |
| 50 | } |
| 51 | } |
| 52 | while ($line =~ m/linkgit:((.*?)\[(\d)\])/g) { |
| 53 | my $pos = pos $line; |
| 54 | my ($target, $page, $section) = ($1, $2, $3); |
| 55 | |
| 56 | # De-AsciiDoc |
| 57 | $page =~ s/{litdd}/--/g; |
| 58 | |
| 59 | if (!exists $TXT{$page}) { |
| 60 | report($pos, $line, $target, "link outside of our own docs"); |
| 61 | next; |
| 62 | } |
| 63 | if (!exists $SECTION{$page}) { |
| 64 | report($pos, $line, $target, "link outside of our sectioned docs"); |
| 65 | next; |
| 66 | } |
| 67 | my $real_section = $SECTION{$page}; |
| 68 | if ($section != $SECTION{$page}) { |
| 69 | report($pos, $line, $target, "wrong section (should be $real_section)"); |
| 70 | next; |
| 71 | } |
| 72 | } |
| 73 | # this resets our $. for each file |
| 74 | close ARGV if eof; |
| 75 | } |
| 76 | |
| 77 | exit $exit_code; |