Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perl-5.8.0 / lib / 5.8.0 / Term / Cap.pm
CommitLineData
86530b38
AT
1package Term::Cap;
2
3use Carp;
4use strict;
5
6use vars qw($VERSION $VMS_TERMCAP);
7use vars qw($termpat $state $first $entry);
8
9$VERSION = '1.07';
10
11# Version undef: Thu Dec 14 20:02:42 CST 1995 by sanders@bsdi.com
12# Version 1.00: Thu Nov 30 23:34:29 EST 2000 by schwern@pobox.com
13# [PATCH] $VERSION crusade, strict, tests, etc... all over lib/
14# Version 1.01: Wed May 23 00:00:00 CST 2001 by d-lewart@uiuc.edu
15# Avoid warnings in Tgetent and Tputs
16# Version 1.02: Sat Nov 17 13:50:39 GMT 2001 by jns@gellyfish.com
17# Altered layout of the POD
18# Added Test::More to PREREQ_PM in Makefile.PL
19# Fixed no argument Tgetent()
20# Version 1.03: Wed Nov 28 10:09:38 GMT 2001
21# VMS Support from Charles Lane <lane@DUPHY4.Physics.Drexel.Edu>
22# Version 1.04: Thu Nov 29 16:22:03 GMT 2001
23# Fixed warnings in test
24# Version 1.05: Mon Dec 3 15:33:49 GMT 2001
25# Don't try to fall back on infocmp if it's not there. From chromatic.
26# Version 1.06: Thu Dec 6 18:43:22 GMT 2001
27# Preload the default VMS termcap from Charles Lane
28# Don't carp at setting OSPEED unless warnings are on.
29# Version 1.07: Wed Jan 2 21:35:09 GMT 2002
30# Sanity check on infocmp output from Norton Allen
31# Repaired INSTALLDIRS thanks to Michael Schwern
32
33# TODO:
34# support Berkeley DB termcaps
35# should probably be a .xs module
36# force $FH into callers package?
37# keep $FH in object at Tgetent time?
38
39=head1 NAME
40
41Term::Cap - Perl termcap interface
42
43=head1 SYNOPSIS
44
45 require Term::Cap;
46 $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed };
47 $terminal->Trequire(qw/ce ku kd/);
48 $terminal->Tgoto('cm', $col, $row, $FH);
49 $terminal->Tputs('dl', $count, $FH);
50 $terminal->Tpad($string, $count, $FH);
51
52=head1 DESCRIPTION
53
54These are low-level functions to extract and use capabilities from
55a terminal capability (termcap) database.
56
57More information on the terminal capabilities will be found in the
58termcap manpage on most Unix-like systems.
59
60=head2 METHODS
61
62=over 4
63
64The output strings for B<Tputs> are cached for counts of 1 for performance.
65B<Tgoto> and B<Tpad> do not cache. C<$self-E<gt>{_xx}> is the raw termcap
66data and C<$self-E<gt>{xx}> is the cached version.
67
68 print $terminal->Tpad($self->{_xx}, 1);
69
70B<Tgoto>, B<Tputs>, and B<Tpad> return the string and will also
71output the string to $FH if specified.
72
73
74=cut
75
76# Preload the default VMS termcap.
77# If a different termcap is required then the text of one can be supplied
78# in $Term::Cap::VMS_TERMCAP before Tgetent is called.
79
80if ( $^O eq 'VMS') {
81 chomp (my @entry = <DATA>);
82 $VMS_TERMCAP = join '', @entry;
83}
84
85# Returns a list of termcap files to check.
86
87sub termcap_path { ## private
88 my @termcap_path;
89 # $TERMCAP, if it's a filespec
90 push(@termcap_path, $ENV{TERMCAP})
91 if ((exists $ENV{TERMCAP}) &&
92 (($^O eq 'os2' || $^O eq 'MSWin32' || $^O eq 'dos')
93 ? $ENV{TERMCAP} =~ /^[a-z]:[\\\/]/is
94 : $ENV{TERMCAP} =~ /^\//s));
95 if ((exists $ENV{TERMPATH}) && ($ENV{TERMPATH})) {
96 # Add the users $TERMPATH
97 push(@termcap_path, split(/(:|\s+)/, $ENV{TERMPATH}))
98 }
99 else {
100 # Defaults
101 push(@termcap_path,
102 $ENV{'HOME'} . '/.termcap',
103 '/etc/termcap',
104 '/usr/share/misc/termcap',
105 );
106 }
107
108 # return the list of those termcaps that exist
109 return grep(-f, @termcap_path);
110}
111
112=item B<Tgetent>
113
114Returns a blessed object reference which the user can
115then use to send the control strings to the terminal using B<Tputs>
116and B<Tgoto>.
117
118The function extracts the entry of the specified terminal
119type I<TERM> (defaults to the environment variable I<TERM>) from the
120database.
121
122It will look in the environment for a I<TERMCAP> variable. If
123found, and the value does not begin with a slash, and the terminal
124type name is the same as the environment string I<TERM>, the
125I<TERMCAP> string is used instead of reading a termcap file. If
126it does begin with a slash, the string is used as a path name of
127the termcap file to search. If I<TERMCAP> does not begin with a
128slash and name is different from I<TERM>, B<Tgetent> searches the
129files F<$HOME/.termcap>, F</etc/termcap>, and F</usr/share/misc/termcap>,
130in that order, unless the environment variable I<TERMPATH> exists,
131in which case it specifies a list of file pathnames (separated by
132spaces or colons) to be searched B<instead>. Whenever multiple
133files are searched and a tc field occurs in the requested entry,
134the entry it names must be found in the same file or one of the
135succeeding files. If there is a C<:tc=...:> in the I<TERMCAP>
136environment variable string it will continue the search in the
137files as above.
138
139The extracted termcap entry is available in the object
140as C<$self-E<gt>{TERMCAP}>.
141
142It takes a hash reference as an argument with two optional keys:
143
144=over 2
145
146=item OSPEED
147
148The terminal output bit rate (often mistakenly called the baud rate)
149for this terminal - if not set a warning will be generated
150and it will be defaulted to 9600. I<OSPEED> can be be specified as
151either a POSIX termios/SYSV termio speeds (where 9600 equals 9600) or
152an old DSD-style speed ( where 13 equals 9600).
153
154
155=item TERM
156
157The terminal type whose termcap entry will be used - if not supplied it will
158default to $ENV{TERM}: if that is not set then B<Tgetent> will croak.
159
160=back
161
162It calls C<croak> on failure.
163
164=cut
165
166sub Tgetent { ## public -- static method
167 my $class = shift;
168 my ($self) = @_;
169
170 $self = {} unless defined $self;
171 bless $self, $class;
172
173 my($term,$cap,$search,$field,$max,$tmp_term,$TERMCAP);
174 local($termpat,$state,$first,$entry); # used inside eval
175 local $_;
176
177 # Compute PADDING factor from OSPEED (to be used by Tpad)
178 if (! $self->{OSPEED}) {
179 if ( $^W ) {
180 carp "OSPEED was not set, defaulting to 9600";
181 }
182 $self->{OSPEED} = 9600;
183 }
184 if ($self->{OSPEED} < 16) {
185 # delays for old style speeds
186 my @pad = (0,200,133.3,90.9,74.3,66.7,50,33.3,16.7,8.3,5.5,4.1,2,1,.5,.2);
187 $self->{PADDING} = $pad[$self->{OSPEED}];
188 }
189 else {
190 $self->{PADDING} = 10000 / $self->{OSPEED};
191 }
192
193 $self->{TERM} = ($self->{TERM} || $ENV{TERM} || croak "TERM not set");
194 $term = $self->{TERM}; # $term is the term type we are looking for
195
196 # $tmp_term is always the next term (possibly :tc=...:) we are looking for
197 $tmp_term = $self->{TERM};
198 # protect any pattern metacharacters in $tmp_term
199 $termpat = $tmp_term; $termpat =~ s/(\W)/\\$1/g;
200
201 my $foo = (exists $ENV{TERMCAP} ? $ENV{TERMCAP} : '');
202
203 # $entry is the extracted termcap entry
204 if (($foo !~ m:^/:s) && ($foo =~ m/(^|\|)${termpat}[:|]/s)) {
205 $entry = $foo;
206 }
207
208 my @termcap_path = termcap_path();
209
210 unless (@termcap_path || $entry)
211 {
212 # last resort--fake up a termcap from terminfo
213 local $ENV{TERM} = $term;
214
215 if ( $^O eq 'VMS' ) {
216 $entry = $VMS_TERMCAP;
217 }
218 else {
219 if ( grep { -x "$_/infocmp" } split /:/, $ENV{PATH} ) {
220 eval
221 {
222 my $tmp = `infocmp -C 2>/dev/null`;
223
224 if (( $tmp !~ m%^/%s ) && ( $tmp =~ /(^|\|)${termpat}[:|]/s)) {
225 $entry = $tmp;
226 }
227 };
228 }
229 }
230 }
231
232 croak "Can't find a valid termcap file" unless @termcap_path || $entry;
233
234 $state = 1; # 0 == finished
235 # 1 == next file
236 # 2 == search again
237
238 $first = 0; # first entry (keeps term name)
239
240 $max = 32; # max :tc=...:'s
241
242 if ($entry) {
243 # ok, we're starting with $TERMCAP
244 $first++; # we're the first entry
245 # do we need to continue?
246 if ($entry =~ s/:tc=([^:]+):/:/) {
247 $tmp_term = $1;
248 # protect any pattern metacharacters in $tmp_term
249 $termpat = $tmp_term; $termpat =~ s/(\W)/\\$1/g;
250 }
251 else {
252 $state = 0; # we're already finished
253 }
254 }
255
256 # This is eval'ed inside the while loop for each file
257 $search = q{
258 while (<TERMCAP>) {
259 next if /^\\t/ || /^#/;
260 if ($_ =~ m/(^|\\|)${termpat}[:|]/o) {
261 chomp;
262 s/^[^:]*:// if $first++;
263 $state = 0;
264 while ($_ =~ s/\\\\$//) {
265 defined(my $x = <TERMCAP>) or last;
266 $_ .= $x; chomp;
267 }
268 last;
269 }
270 }
271 defined $entry or $entry = '';
272 $entry .= $_ if $_;
273 };
274
275 while ($state != 0) {
276 if ($state == 1) {
277 # get the next TERMCAP
278 $TERMCAP = shift @termcap_path
279 || croak "failed termcap lookup on $tmp_term";
280 }
281 else {
282 # do the same file again
283 # prevent endless recursion
284 $max-- || croak "failed termcap loop at $tmp_term";
285 $state = 1; # ok, maybe do a new file next time
286 }
287
288 open(TERMCAP,"< $TERMCAP\0") || croak "open $TERMCAP: $!";
289 eval $search;
290 die $@ if $@;
291 close TERMCAP;
292
293 # If :tc=...: found then search this file again
294 $entry =~ s/:tc=([^:]+):/:/ && ($tmp_term = $1, $state = 2);
295 # protect any pattern metacharacters in $tmp_term
296 $termpat = $tmp_term; $termpat =~ s/(\W)/\\$1/g;
297 }
298
299 croak "Can't find $term" if $entry eq '';
300 $entry =~ s/:+\s*:+/:/g; # cleanup $entry
301 $entry =~ s/:+/:/g; # cleanup $entry
302 $self->{TERMCAP} = $entry; # save it
303 # print STDERR "DEBUG: $entry = ", $entry, "\n";
304
305 # Precompile $entry into the object
306 $entry =~ s/^[^:]*://;
307 foreach $field (split(/:[\s:\\]*/,$entry)) {
308 if (defined $field && $field =~ /^(\w\w)$/) {
309 $self->{'_' . $field} = 1 unless defined $self->{'_' . $1};
310 # print STDERR "DEBUG: flag $1\n";
311 }
312 elsif (defined $field && $field =~ /^(\w\w)\@/) {
313 $self->{'_' . $1} = "";
314 # print STDERR "DEBUG: unset $1\n";
315 }
316 elsif (defined $field && $field =~ /^(\w\w)#(.*)/) {
317 $self->{'_' . $1} = $2 unless defined $self->{'_' . $1};
318 # print STDERR "DEBUG: numeric $1 = $2\n";
319 }
320 elsif (defined $field && $field =~ /^(\w\w)=(.*)/) {
321 # print STDERR "DEBUG: string $1 = $2\n";
322 next if defined $self->{'_' . ($cap = $1)};
323 $_ = $2;
324 s/\\E/\033/g;
325 s/\\(\d\d\d)/pack('c',oct($1) & 0177)/eg;
326 s/\\n/\n/g;
327 s/\\r/\r/g;
328 s/\\t/\t/g;
329 s/\\b/\b/g;
330 s/\\f/\f/g;
331 s/\\\^/\377/g;
332 s/\^\?/\177/g;
333 s/\^(.)/pack('c',ord($1) & 31)/eg;
334 s/\\(.)/$1/g;
335 s/\377/^/g;
336 $self->{'_' . $cap} = $_;
337 }
338 # else { carp "junk in $term ignored: $field"; }
339 }
340 $self->{'_pc'} = "\0" unless defined $self->{'_pc'};
341 $self->{'_bc'} = "\b" unless defined $self->{'_bc'};
342 $self;
343}
344
345# $terminal->Tpad($string, $cnt, $FH);
346
347=item B<Tpad>
348
349Outputs a literal string with appropriate padding for the current terminal.
350
351It takes three arguments:
352
353=over 2
354
355=item B<$string>
356
357The literal string to be output. If it starts with a number and an optional
358'*' then the padding will be increased by an amount relative to this number,
359if the '*' is present then this amount will me multiplied by $cnt. This part
360of $string is removed before output/
361
362=item B<$cnt>
363
364Will be used to modify the padding applied to string as described above.
365
366=item B<$FH>
367
368An optional filehandle (or IO::Handle ) that output will be printed to.
369
370=back
371
372The padded $string is returned.
373
374=cut
375
376sub Tpad { ## public
377 my $self = shift;
378 my($string, $cnt, $FH) = @_;
379 my($decr, $ms);
380
381 if (defined $string && $string =~ /(^[\d.]+)(\*?)(.*)$/) {
382 $ms = $1;
383 $ms *= $cnt if $2;
384 $string = $3;
385 $decr = $self->{PADDING};
386 if ($decr > .1) {
387 $ms += $decr / 2;
388 $string .= $self->{'_pc'} x ($ms / $decr);
389 }
390 }
391 print $FH $string if $FH;
392 $string;
393}
394
395# $terminal->Tputs($cap, $cnt, $FH);
396
397=item B<Tputs>
398
399Output the string for the given capability padded as appropriate without
400any parameter substitution.
401
402It takes three arguments:
403
404=over 2
405
406=item B<$cap>
407
408The capability whose string is to be output.
409
410=item B<$cnt>
411
412A count passed to Tpad to modify the padding applied to the output string.
413If $cnt is zero or one then the resulting string will be cached.
414
415=item B<$FH>
416
417An optional filehandle (or IO::Handle ) that output will be printed to.
418
419=back
420
421The appropriate string for the capability will be returned.
422
423=cut
424
425sub Tputs { ## public
426 my $self = shift;
427 my($cap, $cnt, $FH) = @_;
428 my $string;
429
430 $cnt = 0 unless $cnt;
431
432 if ($cnt > 1) {
433 $string = Tpad($self, $self->{'_' . $cap}, $cnt);
434 } else {
435 # cache result because Tpad can be slow
436 unless (exists $self->{$cap}) {
437 $self->{$cap} = exists $self->{"_$cap"} ?
438 Tpad($self, $self->{"_$cap"}, 1) : undef;
439 }
440 $string = $self->{$cap};
441 }
442 print $FH $string if $FH;
443 $string;
444}
445
446# $terminal->Tgoto($cap, $col, $row, $FH);
447
448=item B<Tgoto>
449
450B<Tgoto> decodes a cursor addressing string with the given parameters.
451
452There are four arguments:
453
454=over 2
455
456=item B<$cap>
457
458The name of the capability to be output.
459
460=item B<$col>
461
462The first value to be substituted in the output string ( usually the column
463in a cursor addressing capability )
464
465=item B<$row>
466
467The second value to be substituted in the output string (usually the row
468in cursor addressing capabilities)
469
470=item B<$FH>
471
472An optional filehandle (or IO::Handle ) to which the output string will be
473printed.
474
475=back
476
477Substitutions are made with $col and $row in the output string with the
478following sprintf() line formats:
479
480 %% output `%'
481 %d output value as in printf %d
482 %2 output value as in printf %2d
483 %3 output value as in printf %3d
484 %. output value as in printf %c
485 %+x add x to value, then do %.
486
487 %>xy if value > x then add y, no output
488 %r reverse order of two parameters, no output
489 %i increment by one, no output
490 %B BCD (16*(value/10)) + (value%10), no output
491
492 %n exclusive-or all parameters with 0140 (Datamedia 2500)
493 %D Reverse coding (value - 2*(value%16)), no output (Delta Data)
494
495The output string will be returned.
496
497=cut
498
499sub Tgoto { ## public
500 my $self = shift;
501 my($cap, $code, $tmp, $FH) = @_;
502 my $string = $self->{'_' . $cap};
503 my $result = '';
504 my $after = '';
505 my $online = 0;
506 my @tmp = ($tmp,$code);
507 my $cnt = $code;
508
509 while ($string =~ /^([^%]*)%(.)(.*)/) {
510 $result .= $1;
511 $code = $2;
512 $string = $3;
513 if ($code eq 'd') {
514 $result .= sprintf("%d",shift(@tmp));
515 }
516 elsif ($code eq '.') {
517 $tmp = shift(@tmp);
518 if ($tmp == 0 || $tmp == 4 || $tmp == 10) {
519 if ($online) {
520 ++$tmp, $after .= $self->{'_up'} if $self->{'_up'};
521 }
522 else {
523 ++$tmp, $after .= $self->{'_bc'};
524 }
525 }
526 $result .= sprintf("%c",$tmp);
527 $online = !$online;
528 }
529 elsif ($code eq '+') {
530 $result .= sprintf("%c",shift(@tmp)+ord($string));
531 $string = substr($string,1,99);
532 $online = !$online;
533 }
534 elsif ($code eq 'r') {
535 ($code,$tmp) = @tmp;
536 @tmp = ($tmp,$code);
537 $online = !$online;
538 }
539 elsif ($code eq '>') {
540 ($code,$tmp,$string) = unpack("CCa99",$string);
541 if ($tmp[$[] > $code) {
542 $tmp[$[] += $tmp;
543 }
544 }
545 elsif ($code eq '2') {
546 $result .= sprintf("%02d",shift(@tmp));
547 $online = !$online;
548 }
549 elsif ($code eq '3') {
550 $result .= sprintf("%03d",shift(@tmp));
551 $online = !$online;
552 }
553 elsif ($code eq 'i') {
554 ($code,$tmp) = @tmp;
555 @tmp = ($code+1,$tmp+1);
556 }
557 else {
558 return "OOPS";
559 }
560 }
561 $string = Tpad($self, $result . $string . $after, $cnt);
562 print $FH $string if $FH;
563 $string;
564}
565
566# $terminal->Trequire(qw/ce ku kd/);
567
568=item B<Trequire>
569
570Takes a list of capabilities as an argument and will croak if one is not
571found.
572
573=cut
574
575sub Trequire { ## public
576 my $self = shift;
577 my($cap,@undefined);
578 foreach $cap (@_) {
579 push(@undefined, $cap)
580 unless defined $self->{'_' . $cap} && $self->{'_' . $cap};
581 }
582 croak "Terminal does not support: (@undefined)" if @undefined;
583}
584
585=back
586
587=head1 EXAMPLES
588
589 use Term::Cap;
590
591 # Get terminal output speed
592 require POSIX;
593 my $termios = new POSIX::Termios;
594 $termios->getattr;
595 my $ospeed = $termios->getospeed;
596
597 # Old-style ioctl code to get ospeed:
598 # require 'ioctl.pl';
599 # ioctl(TTY,$TIOCGETP,$sgtty);
600 # ($ispeed,$ospeed) = unpack('cc',$sgtty);
601
602 # allocate and initialize a terminal structure
603 $terminal = Tgetent Term::Cap { TERM => undef, OSPEED => $ospeed };
604
605 # require certain capabilities to be available
606 $terminal->Trequire(qw/ce ku kd/);
607
608 # Output Routines, if $FH is undefined these just return the string
609
610 # Tgoto does the % expansion stuff with the given args
611 $terminal->Tgoto('cm', $col, $row, $FH);
612
613 # Tputs doesn't do any % expansion.
614 $terminal->Tputs('dl', $count = 1, $FH);
615
616=head1 COPYRIGHT AND LICENSE
617
618Please see the README file in distribution.
619
620=head1 AUTHOR
621
622This module is part of the core Perl distribution and is also maintained
623for CPAN by Jonathan Stowe <jns@gellyfish.com>.
624
625=head1 SEE ALSO
626
627termcap(5)
628
629=cut
630
631# Below is a default entry for systems where there are terminals but no
632# termcap
6331;
634__DATA__
635vt220|vt200|DEC VT220 in vt100 emulation mode:
636am:mi:xn:xo:
637co#80:li#24:
638RA=\E[?7l:SA=\E[?7h:
639ac=kkllmmjjnnwwqquuttvvxx:ae=\E(B:al=\E[L:as=\E(0:
640bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:
641cr=^M:cs=\E[%i%d;%dr:dc=\E[P:dl=\E[M:do=\E[B:
642ei=\E[4l:ho=\E[H:im=\E[4h:
643is=\E[1;24r\E[24;1H:
644nd=\E[C:
645kd=\E[B::kl=\E[D:kr=\E[C:ku=\E[A:le=^H:
646mb=\E[5m:md=\E[1m:me=\E[m:mr=\E[7m:
647kb=\0177:
648r2=\E>\E[24;1H\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E=:rc=\E8:
649sc=\E7:se=\E[27m:sf=\ED:so=\E[7m:sr=\EM:ta=^I:
650ue=\E[24m:up=\E[A:us=\E[4m:ve=\E[?25h:vi=\E[?25l:
651