Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defined(&constantsub) always returns FALSE for imported constants #6026

Open
p5pRT opened this issue Oct 21, 2002 · 5 comments
Open

defined(&constantsub) always returns FALSE for imported constants #6026

p5pRT opened this issue Oct 21, 2002 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 21, 2002

Migrated from rt.perl.org#18046 (status was 'open')

Searchable as RT18046$

@p5pRT
Copy link
Author

p5pRT commented Oct 21, 2002

From @jimav

Created by @jimav

use Fcntl;
printf "O_RDWR is %d\n", &O_RDWR; # no warning or error
die "Error, O_RDWR not defined" unless defined (&O_RDWR); #
***DIES HERE***

This is inconsistent, and is a real user problem if a symbol may or
may
not actually be exported by the package used. If the symbol is not
actually exported, the program must not use it; but the program
can't
test for this condition! For example​:

  use strict;
  use Fcntl;
  if (defined &O_FOOBAR) {
  printf "O_FOOBAR = %s\n", &O_FOOBAR; # case 1
  } else {
  die "O_FOOBAR not defined, so I won't use it\n"; # case 2
  }

if O_FOOBAR is undefined, it hits case 2 (correct).
if O_FOOBAR is a locally-defined sub, it hits case 1 (correct).
if O_FOOBAR is replaced by O_RDWR, it hits case 2 (WRONG).

I hit this problem trying to use O_BINARY on Doshish platforms.
sysopen *must* be passed O_BINARY to avoid CR-LF translations.
But O_BINARY presumably might not be defined on Unix platforms.
So I tried this​:
  use Fcntl;
  if (defined &O_BINARY) {
  sysopen(FILE,$path, O_RDONLY|O_BINARY) ...
  } else {
  sysopen(FILE,$path, O_RDONLY) ...
  }
This FAILED because the second branch was always taken, even on
Windows
where O_BINARY is in fact defined.

I'm not certain whether or not O_BINARY is defined on all
platforms,
but that's the whole point... programs should be able to test
whether
or not a constant is in fact exported from a package which it is
using.

Cheers.

Perl Info

Flags:
    category=core
    severity=high

Site configuration information for perl v5.6.1:

Configured by root at Mon Mar  4 11:19:37 PST 2002.

Summary of my perl5 (revision 5.0 version 6 subversion 1)
configuration:
  Platform:
    osname=linux, osvers=2.4.7-10smp, archname=i686-linux
    uname='linux tribble.simplex.com 2.4.7-10smp #1 smp thu sep 6
17:09:31 edt 2
001 i686 unknown '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef
usemultiplicity=unde
f
    useperlio=undef d_sfio=undef uselargefiles=define
usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
  Compiler:
    cc='gcc', ccflags ='-fno-strict-aliasing -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_
BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing'
    ccversion='', gccversion='2.96 20000731 (Red Hat Linux 7.1
2.96-98)', gccosa
ndvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define,
longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8,
Off_t='off_t', lseeksize
=8
    alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =''
    libpth=/lib /usr/lib
    libs=-lnsl -lgdbm -ldb -ldl -lm -lc -lcrypt -lutil
    perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil
    libc=/lib/libc-2.2.4.so, so=so, useshrplib=false,
libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef,
ccdlflags='-rdynamic'
    cccdlflags='-fpic', lddlflags='-shared'

Locally applied patches:
    


@INC for perl v5.6.1:
    /usr/local/lib/perl5/5.6.1/i686-linux
    /usr/local/lib/perl5/5.6.1
    /usr/local/lib/perl5/site_perl/5.6.1/i686-linux
    /usr/local/lib/perl5/site_perl/5.6.1
    /usr/local/lib/perl5/site_perl
    .


Environment for perl v5.6.1:
    HOME=/home/jima
    LANG=en_US
    LANGUAGE (unset)
    LC_COLLATE=POSIX
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
   
PATH=output/linux_x86/bin:libdft/src:../../output/linux_x86/bin:../../libdft
/src:/home/jima/work-branch/output/linux_x86/bin:/home/jima/work-branch/libdft/s
rc:/home/jima/work/output/linux_x86/bin:/home/jima/work/libdft/src:/home/jima/wo
rk.mess/output/linux_x86/bin:/home/jima/work.mess/libdft/src:/home/jima/bin/linu
x_x86:/home/jima/bin:/home/jima/jima_tools/linux_x86/bin:/usr/local/bin:/usr/loc
al/gcc/3.1/bin:/usr/local/gcc/gdb-5.2/bin:/bin:/usr/bin/X11:/usr/sbin:/opt/vnc/b
in:/opt/mozilla:/opt/jima/bin:/usr/bin:/usr/X11R6/bin:/usr/games:/opt/kde3/bin:/
usr/lib/java/bin:/opt/gnome/bin:.
    PERL_BADLANG (unset)
    SHELL=/bin/bash



=====
__________________________________________________
Please do not put me on a mailing list or give my 
address(es) to anyone else.

__________________________________________________
Do you Yahoo!?
Y! Web Hosting - Let the expert host your web site
http://webhosting.yahoo.com/

@p5pRT
Copy link
Author

p5pRT commented Oct 22, 2002

From @rgs

Jim Avera (via RT) <perlbug@​perl.org> wrote​:

use Fcntl;
printf "O_RDWR is %d\n", &O_RDWR; # no warning or error
die "Error, O_RDWR not defined" unless defined (&O_RDWR); #
***DIES HERE***

In fact, the Fcntl constants are AUTOLOAD'ed.
To check whether they exist, you should use exists() rather than
defined().
HTH.

@p5pRT
Copy link
Author

p5pRT commented Oct 22, 2002

From @eserte

Jim Avera (via RT) <perlbug@​perl.org> writes​:

# New Ticket Created by Jim Avera
# Please include the string​: [perl #18046]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt2/Ticket/Display.html?id=18046 >

This is a bug report for perl from james_avera@​yahoo.com,
generated with the help of perlbug 1.33 running under perl v5.6.1.

-----------------------------------------------------------------
[Please enter your report here]

use Fcntl;
printf "O_RDWR is %d\n", &O_RDWR; # no warning or error
die "Error, O_RDWR not defined" unless defined (&O_RDWR); #
***DIES HERE***

This is inconsistent, and is a real user problem if a symbol may or
may
not actually be exported by the package used. If the symbol is not
actually exported, the program must not use it; but the program
can't
test for this condition! For example​:

use strict;
use Fcntl;
if (defined &O_FOOBAR) {
printf "O_FOOBAR = %s\n", &O_FOOBAR; # case 1
} else {
die "O_FOOBAR not defined, so I won't use it\n"; # case 2
}

if O_FOOBAR is undefined, it hits case 2 (correct).
if O_FOOBAR is a locally-defined sub, it hits case 1 (correct).
if O_FOOBAR is replaced by O_RDWR, it hits case 2 (WRONG).

I hit this problem trying to use O_BINARY on Doshish platforms.
sysopen *must* be passed O_BINARY to avoid CR-LF translations.
But O_BINARY presumably might not be defined on Unix platforms.
So I tried this​:
use Fcntl;
if (defined &O_BINARY) {
sysopen(FILE,$path, O_RDONLY|O_BINARY) ...
} else {
sysopen(FILE,$path, O_RDONLY) ...
}
This FAILED because the second branch was always taken, even on
Windows
where O_BINARY is in fact defined.

I'm not certain whether or not O_BINARY is defined on all
platforms,
but that's the whole point... programs should be able to test
whether
or not a constant is in fact exported from a package which it is
using.

This is documented in the perlsub documentation for "defined"​:

| Note that a subroutine which is not defined may still be callable​: its
| package may have an AUTOLOAD method that makes it spring into
| existence the first time that it is called -- see the perlsub manpage.

You can use "exists" instead, because "exists" checks whether a
subroutine is declared, which seems to be the case for exported
subroutines and constants. As a last resort, you can always test for
constants and subroutines in a eval { } block.

Rehards,
  Slaven

--
Slaven Rezic - slaven.rezic@​berlin.de

  tkruler - Perl/Tk program for measuring screen distances
  http​://ptktools.sourceforge.net/#tkruler

@p5pRT
Copy link
Author

p5pRT commented Oct 24, 2002

From @jimav

Thanks. But...

perlfunc (under 'exists') says​:
  "Note that a subroutine which does not exist may still be
  callable​: its package may have an "AUTOLOAD" method that makes
  it spring into existence the first time that it is called..."

This implies that exists(&subname) returns FALSE for an
AUTOLOADED sub which has not yet been loaded.

This contradicts reality.
Perhaps perlfunc could be clarified at this point.

-Jim

--- Rafael Garcia-Suarez <perlbug@​perl.org> wrote​:

Jim Avera (via RT) <perlbug@​perl.org> wrote​:

use Fcntl;
printf "O_RDWR is %d\n", &O_RDWR; # no warning or error
die "Error, O_RDWR not defined" unless defined (&O_RDWR); #
***DIES HERE***

In fact, the Fcntl constants are AUTOLOAD'ed.
To check whether they exist, you should use exists() rather than
defined().
HTH.

=====
__________________________________________________
Please do not put me on a mailing list or give my
address(es) to anyone else.

__________________________________________________
Do you Yahoo!?
Y! Web Hosting - Let the expert host your web site
http​://webhosting.yahoo.com/

@p5pRT
Copy link
Author

p5pRT commented Oct 3, 2010

From @cpansprout

On Wed Oct 23 22​:44​:42 2002, jimav wrote​:

Thanks. But...

perlfunc (under 'exists') says​:
"Note that a subroutine which does not exist may still be
callable​: its package may have an "AUTOLOAD" method that makes
it spring into existence the first time that it is called..."

This implies that exists(&subname) returns FALSE for an
AUTOLOADED sub which has not yet been loaded.

This contradicts reality.

It’s true that non-existent functions can be AUTOLOADed. But you can’t
export a non-existent function. It has to exist for that, but it does
not have to be defined.

So, if Fcntl does not export FROMP, then &FROMP will call
main​::AUTOLOAD, if present.
If it does export FROMP then &FROMP will call Fcntl​::AUTOLOAD.

Perhaps perlfunc could be clarified at this point.

Any suggestions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants