txicmdcheck 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #!/usr/bin/env perl
  2. # $Id$
  3. # Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
  4. # Free Software Foundation, Inc.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 3 of the License,
  9. # or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. # Original author: Karl Berry.
  20. #
  21. # Kludge of a script to check command lists in refcard vs. refman vs.
  22. # tp for consistency.
  23. exit (&main ());
  24. sub main {
  25. my $no_common = $ARGV[0] eq "--no-common";
  26. my %card_cmds = &read_refcard ("txirefcard.tex");
  27. my %idx_cmds = &read_refidx ("../texinfo.texi");
  28. my %man_cmds = &read_refman ("../texinfo.texi");
  29. my %tp_cmds = &read_tp ("../../util/txicmdlist");
  30. # find the commands that are covered everywhere.
  31. my @found = ();
  32. for my $cc (keys %card_cmds) {
  33. if (exists $idx_cmds{$cc}
  34. && exists $man_cmds{$cc}
  35. && exists $tp_cmds{$cc}) {
  36. push (@found, $cc);
  37. delete $card_cmds{$cc};
  38. delete $idx_cmds{$cc};
  39. delete $man_cmds{$cc};
  40. delete $tp_cmds{$cc};
  41. }
  42. }
  43. printf (" common %d: @{[sort @found]}\n", @found + 0)
  44. unless $no_common;
  45. # there are numerous @findex entries which are not @-commands, which
  46. # can be seen this way:
  47. #my @idx_only = keys %idx_cmds;
  48. #printf "findex only %s: @{[sort @idx_only]}\n", @idx_only + 0;
  49. #
  50. # let's not report those, but we do want to report normal commands that
  51. # did not have findex entries: those which are present in all the
  52. # other lists.
  53. my @idx_missing = ();
  54. for my $cc (sort keys %card_cmds) {
  55. if (exists $man_cmds{$cc} && exists $tp_cmds{$cc}) {
  56. push (@idx_missing, $cc);
  57. delete $card_cmds{$cc};
  58. delete $man_cmds{$cc};
  59. delete $tp_cmds{$cc};
  60. }
  61. }
  62. printf "findex missing %s: @idx_missing\n", @idx_missing + 0
  63. if @idx_missing;
  64. # now report on commands only in some other subset.
  65. my @card_only = keys %card_cmds;
  66. printf "refcard only %s: @{[sort @card_only]}\n", @card_only + 0;
  67. my @man_only = keys %man_cmds;
  68. printf "refman only %s: @{[sort @man_only]}\n", @man_only + 0;
  69. my @tp_only = keys %tp_cmds;
  70. printf "tp only %s: @{[sort @tp_only]}\n", @tp_only + 0;
  71. return @card_only + @man_only + @tp_only;
  72. }
  73. # Return command names from the reference card as the keys of a hash
  74. # (with empty values). In principle it's a list, but as a practical
  75. # matter we want to work with a hash anyway, so we might as well return
  76. # it that way in the first place. (Ditto for the other functions.)
  77. #
  78. sub read_refcard {
  79. my ($fname) = @_;
  80. my @ret = ();
  81. local *FILE;
  82. $FILE = $fname;
  83. open (FILE) || die "open($FILE) failed: $!";
  84. while (<FILE>) {
  85. next unless /^\\txicmd/;
  86. chomp;
  87. my $xcmd = 0;
  88. s/\\txicmdarg\{.*?\}\}?//; # first get rid of the arguments
  89. s/\}\{.*//; # then the descriptions
  90. s/^\\txicmdx\{// && ($xcmd = 1); # used for the @def...x
  91. s/^\\txicmd\{//; # finally the markup cmd itself
  92. s/\\ttbraced\{\}//g; # quote cmd list
  93. my (@cmds) = split (/,? +/, $_); # occasionally we combine cmds
  94. # we typeset these specially in TeX.
  95. if ("@cmds" eq "@#1footing") {
  96. @cmds = ('@oddfooting', '@evenfooting', '@everyfooting');
  97. } elsif ("@cmds" eq "@#1heading") {
  98. @cmds = ('@oddheading', '@evenheading', '@everyheading');
  99. }
  100. # add each command from this line to the return.
  101. for my $c (@cmds) {
  102. #warn "refcard $c\n";
  103. #warn "refcard $c{x}\n" if $xcmd;
  104. next if $c eq "txicommandconditionals"; # variable not separate in manual
  105. if ($c eq '@\tildechar') { # TeX specialties, forcibly make them match
  106. $c = '@~';
  107. } elsif ($c eq '@\var{whitespace}') {
  108. $c = '@var{whitespace}';
  109. }
  110. $c = '@~' if $c eq '@\tildechar'; # TeX
  111. $c = '@\\' if $c eq '@\bschar'; # TeX
  112. $c = '@{' if $c eq '@\lbracechar'; # TeX
  113. $c = '@}' if $c eq '@\rbracechar'; # TeX
  114. push (@ret, $c);
  115. push (@ret, "${c}x") if $xcmd;
  116. }
  117. }
  118. push (@ret, '@end', '@uref', '@appendixsection'); # described in text
  119. push (@ret, '@,'); # our non-parsing above lost these
  120. push (@ret, qw(@atchar @lbracechar @rbracechar @backslashchar));
  121. close (FILE) || warn "close($FILE) failed: $!";
  122. my %ret; @ret{@ret} = ();
  123. return %ret;
  124. }
  125. # Return command names from @findex entries in the reference manual as
  126. # the keys of a hash (empty values).
  127. #
  128. sub read_refidx {
  129. my ($fname) = @_;
  130. my @ret = ();
  131. local *FILE;
  132. $FILE = $fname;
  133. open (FILE) || die "open($FILE) failed: $!";
  134. while (<FILE>) {
  135. next unless s/^\@findex\s+//; # only consider @findex lines
  136. chomp;
  137. s/\s+\@r.*$//;# if /^[^a-zA-Z]/; # remove comment
  138. s/\@\{\@\}//; # remove @{@} used in atchar, etc.
  139. s/<colon>/:/; # @:
  140. s/<newline>/var{whitespace}/; # special generic entry: @var{whitespace}
  141. s/^/\@/ unless /^\@/; # prepend @ unless already there (@@ @{ @})
  142. push (@ret, $_);
  143. }
  144. close (FILE) || warn "close($FILE) failed: $!";
  145. my %ret; @ret{@ret} = ();
  146. return %ret;
  147. }
  148. # Return command names from the @-Command List node in the reference
  149. # manual as the keys of a hash (empty values).
  150. #
  151. sub read_refman {
  152. my ($fname) = @_;
  153. my @ret = ();
  154. local *FILE;
  155. $FILE = $fname;
  156. open (FILE) || die "open($FILE) failed: $!";
  157. while (<FILE>) {
  158. last if /^\@section \@\@-Command List/; # ignore until right section
  159. }
  160. while (<FILE>) {
  161. last if /^\@end table/; # ignore again after the summary
  162. next unless s/^\@itemx? *\@//; # only want item[x]s in the table
  163. chomp;
  164. s/\@\{.+//; # remove braced arguments (but not @{)
  165. s/ .*//; # remove arguments following a space
  166. s/\@\@/@/g; # @@ -> @
  167. next if $_ =~ /^\@(br|ctrl)$/; # @ignore-d in text
  168. push (@ret, $_);
  169. }
  170. push (@ret, '@{'); # our non-parsing above fails on this one
  171. close (FILE) || warn "close($FILE) failed: $!";
  172. my %ret; @ret{@ret} = ();
  173. return %ret;
  174. }
  175. # Return command names implemented in the general parser as the keys of
  176. # a hash (empty values). The argument is the command to run to return
  177. # the list.
  178. #
  179. sub read_tp {
  180. my ($prog) = @_;
  181. my @ret = ();
  182. local *FILE;
  183. $FILE = "$prog |";
  184. open (FILE) || die "open($FILE) failed: $!";
  185. while (<FILE>) {
  186. chomp;
  187. # excise @<whitespace> commands from normal list.
  188. next if $_ eq '@ ' || $_ eq "\@\t" || $_ eq "" || $_ eq '@';
  189. # obsolete and/or subsidiary commands we don't want to document as usual.
  190. next if $_ =~ /allow-recursion
  191. |columnfractions
  192. |cropmarks
  193. |ctrl
  194. |(even|every|odd)(foot|head)ingmarks
  195. |quote-arg
  196. |rmacro
  197. |set(short)?contentsaftertitlepage
  198. |shorttitle$
  199. |\|
  200. /x;
  201. push (@ret, $_);
  202. }
  203. close (FILE) || warn "close($FILE) failed: $!";
  204. push (@ret, '@var{whitespace}');
  205. my %ret; @ret{@ret} = ();
  206. return %ret;
  207. }