| #!/usr/bin/perl | |
| use strict; | |
| use warnings; | |
| # Parse arguments, a simple state machine for input like: | |
| # | |
| # <file-to-check.adoc> <valid-files-to-link-to> --section=1 git.adoc git-add.adoc [...] --to-lint git-add.adoc a-file.adoc [...] | |
| my %TXT; | |
| my %SECTION; | |
| my $section; | |
| my $lint_these = 0; | |
| my $to_check = shift @ARGV; | |
| for my $arg (@ARGV) { | |
| if (my ($sec) = $arg =~ /^--section=(\d+)$/s) { | |
| $section = $sec; | |
| next; | |
| } | |
| my ($name) = $arg =~ /^(.*?)\.adoc$/s; | |
| unless (defined $section) { | |
| $TXT{$name} = $arg; | |
| next; | |
| } | |
| $SECTION{$name} = $section; | |
| } | |
| my $exit_code = 0; | |
| sub report { | |
| my ($pos, $line, $target, $msg) = @_; | |
| substr($line, $pos) = "' <-- HERE"; | |
| $line =~ s/^\s+//; | |
| print STDERR "$ARGV:$.: error: $target: $msg, shown with 'HERE' below:\n"; | |
| print STDERR "$ARGV:$.:\t'$line\n"; | |
| $exit_code = 1; | |
| } | |
| @ARGV = sort values %TXT; | |
| die "BUG: No list of valid linkgit:* files given" unless @ARGV; | |
| @ARGV = $to_check; | |
| while (<>) { | |
| my $line = $_; | |
| while ($line =~ m/(.{,8})((git[-a-z]+|scalar)\[(\d)*\])/g) { | |
| my $pos = pos $line; | |
| my ($macro, $target, $page, $section) = ($1, $2, $3, $4); | |
| if ( $macro ne "linkgit:" && $macro !~ "ifn?def::" && $macro ne "endif::" ) { | |
| report($pos, $line, $target, "linkgit: macro expected"); | |
| } | |
| } | |
| while ($line =~ m/linkgit:((.*?)\[(\d)\])/g) { | |
| my $pos = pos $line; | |
| my ($target, $page, $section) = ($1, $2, $3); | |
| # De-AsciiDoc | |
| $page =~ s/{litdd}/--/g; | |
| if (!exists $TXT{$page}) { | |
| report($pos, $line, $target, "link outside of our own docs"); | |
| next; | |
| } | |
| if (!exists $SECTION{$page}) { | |
| report($pos, $line, $target, "link outside of our sectioned docs"); | |
| next; | |
| } | |
| my $real_section = $SECTION{$page}; | |
| if ($section != $SECTION{$page}) { | |
| report($pos, $line, $target, "wrong section (should be $real_section)"); | |
| next; | |
| } | |
| } | |
| # this resets our $. for each file | |
| close ARGV if eof; | |
| } | |
| exit $exit_code; |