1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
#!/usr/bin/env perl
# helpfiles: make help files for Z-shell builtins from the manual entries.
# Create help files for zsh commands for the manpage file of zshbuildins.1
# passed as the first arg.
# The second arg is the directory in which the help files will be created.
# Assumes no other files are present.
# No overwriting check; `.' becomes `dot', `:' becomes `colon'.
# Any command claiming to be `same as <foo>' or `equivalent to <foo>'
# has its help file appended to the end of <foo>'s and replaced by a
# link to <foo>. (Arguably the help file should be put at the start
# instead.)
# If a third arg is given, the symlink is not created, but a
# list of symlinks is put into the file specified by that arg.
# This script is called automatically during `make install'
# unless specified otherwise.
# For usage and more information see zshcontrib(1).
sub Usage {
print(STDERR "Usage: helpfiles zshbuiltins.1 dest-dir [link-file]\n");
exit(1);
}
sub Info {
print('helpfiles: ', @_, "\n");
}
sub Die {
print(STDERR 'helpfiles: ', @_, "\n");
exit(1);
}
&Usage() unless(@ARGV);
$manfile = shift(@ARGV);
&Usage() unless(@ARGV);
$destdir = shift(@ARGV);
$linkfile = ((@ARGV) ? shift(@ARGV) : '');
unless(-d $destdir) {
mkdir($destdir) || &Die("$destdir is not a directory and cannot be created");
}
foreach (keys %ENV) {
delete($ENV{$_}) if(/^((LC_)|(LESS)|(MAN))/);
}
$ENV{'LANG'} = 'C';
$ENV{'MANWIDTH'} = '80';
$ENV{'GROFF_NO_SGR'} = ''; # We need "classical" formatting of man pages.
$mantmp = $destdir . '/man.tmp';
$coltmpbase = 'col.tmp';
$coltmp = $destdir . '/' . $coltmpbase;
$args = "$manfile >$mantmp";
unlink($mantmp);
&Info('attempting man ', $args);
if(system('man ' . $args) || !(-s $mantmp)) {
unlink($mantmp);
&Info('attempting nroff -man ', $args);
if(system('nroff -man ' . $args) || !(-s $mantmp)) {
unlink($mantmp);
&Die('man and nroff -man both failed for ', $manfile);
}
}
$args = "$mantmp >$coltmp";
unlink($coltmp);
&Info('attempting col -bx <', $args);
# The x is necessary so that spaces don't turn into tabs, which messes
# up the calculations of indentation on machines which randomly wrap lines
# round to the previous line (so you see what we're up against).
if(system('col -bx <' . $args) || !(-s $coltmp)) {
unlink($coltmp);
&Info('attempting colcrt - ', $args);
if(system('colcrt - ' . $args) || !(-s $coltmp)) {
unlink($mantmp);
unlink($coltmp);
&Die('col -bx and colcrt - both failed');
}
}
unlink($mantmp) || &Die('cannot remove tempfile ', $mantmp);
unless(open(MANPAGE, '<', $coltmp)) {
unlink($coltmp);
&Die('generated tmpfile cannot be read');
}
unless($linkfile eq '') {
open(LINKFILE, '>', $linkfile) || &Die("cannot open $linkfile for writing")
}
chdir($destdir) || &Die("cannot cd to $destdir");
while (<MANPAGE>) {
last if /^\s*SHELL BUILTIN COMMANDS/;
/zshbuiltins/ && $zb++;
last if ($zb && /^\s*DESCRIPTIONS/);
}
$print = 0;
sub namesub {
local($cmd) = shift;
if ($cmd =~ /^\w*$/ && lc($cmd) eq $cmd) {
$cmd;
} elsif ($cmd eq '.') {
'dot';
} elsif ($cmd eq ':') {
'colon';
} else {
undef;
}
}
sub getsame {
local($_) = shift;
if (/same\s*as\s*(\S+)/i || /equivalent\s*to\s*(\S+)/i) {
local($name) = $1;
($name =~ /[.,]$/) && chop($name);
return $name;
} else {
return undef;
}
}
sub newcmd {
local($_) = shift;
local($cmd);
# new command
if (defined($cmd = &namesub($_))) {
# in case there's something nasty here like a link..
unlink $cmd;
open (OUT, ">$cmd");
select OUT;
$print = 1;
} else {
$print = 0;
}
}
sub doprint {
local($_) = shift;
s/^$indentstr//o; # won't work if too many tabs
print;
}
while (<MANPAGE>) { last unless /^\s*$/; }
/^(\s+)(\S+)/;
$indentstr = $1;
$indent = length($1);
&newcmd($2);
print if $print;
BUILTINS: while (<MANPAGE>) {
next if /^\w/;
undef($undented);
if (/^\s*$/ || ($undented = (/^(\s*)/ && length($1) < $indent))) {
$undented && &doprint($_);
while (defined($_ = <MANPAGE>) && /(^\w)|(^\s*$)/) {
# NAME is the start of the next section when in zshall.
# (Historical note: we used to exit on the page header,
# but text from the old section can continue to the
# new page).
last BUILTINS if /^\s*NAME\s*$/;
last BUILTINS if /^STARTUP\/SHUTDOWN FILES/;
last if /^zsh.*\s\d$/; # GNU nroff -man end-of-page marker
}
if (/^\s*Page/ || /^zsh.*\s\d$/) {
do {
$_ = <MANPAGE>;
} while (defined($_) && /^\s*$/);
if (/^\s*ZSHBUILTINS/) {
do {
$_ = <MANPAGE>;
} while (defined($_) && /^\s*$/);
}
}
if (/^(\s*)/ && length($1) < $indent) {
# This may be just a bug on the SGI, or maybe something
# more sinister (don\'t laugh, this is nroff).
s/^\s*/ /;
$defer = $_;
do {
$_ = <MANPAGE>;
} while (defined($_) && /^\s*$/);
last unless defined($_);
}
if (/^(\s+)(\S+)/ && length($1) == $indent) {
&newcmd($2);
} else {
print "\n";
}
if ($print) {
if (defined($defer)) {
chop;
&doprint("$_$defer");
undef($defer);
} else {
&doprint($_);
}
}
} else {
&doprint($_) if $print;
}
}
select STDOUT;
close OUT;
close(MANPAGE);
unlink($coltmpbase) || &Die('cannot remove tempfile ', $coltmpbase);
foreach $file (<*>) {
open (IN, $file);
if ($sameas = (&getsame($_ = <IN>) || &getsame($_ = <IN>))) {
defined($sameas = &namesub($sameas)) || next;
# print "$file is the same as $sameas\n";
seek (IN, 0, 0);
# Copy this to base builtin.
open (OUT, ">>$sameas");
select OUT;
print "\n";
while (<IN>) { print; }
close IN;
select STDOUT;
close OUT;
# Make this a link to that.
unlink $file;
if($linkfile eq '') {
symlink ($sameas, $file);
} else {
print(LINKFILE "$sameas $file\n");
}
}
}
close(LINKFILE) unless($linkfile eq '');
# Make one sanity check
&Die('not all files were properly generated') unless(-r 'ztcp');
__END__
|