[comp.lang.perl] new user findings

matt@snave.Eng.Sun.COM (Matt Evans) (05/23/91)

Hello Perl users;


I've just started using perl (perl 4.0 on SUNOS 4.1.1 sun4c) and I 
have some questions relating to the following problems I
seen ...


=======================
 1) caller command:
=======================


   PERL core dumps on the following 
   code:


#!/usr/local/bin/perl
#---------------------------
# start test (caller) main
#---------------------------

   $prog_dir = "./";
   $prog_name = "not_here";


   open (ERR_LOG,">./perr");

   $proc_name = join ("",$prog_dir,$prog_name);
   if (!( -e $conv_proc_name)) {
	&conv_err ("can't access the program",1);
   }

sub conv_err {

    local($err_msg,$err_code) = @_; # sub arguments


    #
    # local variable declaration
    #

    local($pack);      
    local($file);      
    local($line);      
    local($sub_name); 


    #
    # after debugging the core file, it seems perl
    # dies on the next line
    #


    ($pack,$file,$line,$sub_name) = caller (0);


    if ($err_code == $FATAL_ERR) {
       print ERR_LOG "\n\n ERROR:$pack:$sub_name:$file:$line";
       die "exit test tool";
    }
    else {
          print ERR_LOG "\n\n ERROR:$pack:$sub_name:$file:$line";
    }
   
}

================================
 2) numeric & string equalities
================================

 In reading the camel book, it seems there should be no problem
 in comparing strings and numbers, However the behavior of the 
 following perl code seems inconsistent:


#!/asdf/bin/perl

 $x = "test";
 if ($x == 0) {
    print "x is equal to 0\n";
 }
 if ($x eq "test") {
    print "x is equal to the str \"test\"\n";
 }

 ------------------------------------------

 output:

 x is equal to 0
 x is equal to the str "test"


 Question: Why does $x compare equally to numeric 0? Is this
	   correct behavior?
 

================================
 3) tom christiansen's open2.pl
================================

 This is more of a question and a FYI. I was using the open2.pl
 routine to fire off a process from perl. The routine works
 like a champ, but it has an interesting side effect. This side
 effect actually occurs in the spawned process. The spawned
 process I was running does an fstat on STDIN to tell if it
 has been started interactively from a terminal  or if it
 has been spawned using pipes. (this C program does many things
 differently based on whether it is started from pipes or
 a character device).

   C code snipit:

     if ((sbuf.st_mode & S_IFMT) == S_IFCHR) {
        input_term = TRUE;
     }
     else {
           input_term = FALSE;
     }

 well, if the process is started from perl using open2.pl the
 process thinks it was started from a terminal i.e from above
 the var input_term is assigned to TRUE.

 I wrote  C program to emulate open2.pl with the sequence
 of using pipe,fork then exec. The above process did in fact
 register that it is NOT started from a terminal and the C statement
 (sbuf.st_mode & S_IFMT) is actually equal to S_IFIFO. This is
 also true if a process is started from the sh pipe ('|') .

 So the question goes to all the perl internals wizards:

 Is there any hidden things happening with PERL's pipe, fork 
 and exec commands that would explain the results I'm getting from
 that fstat routine on the spawned program? 
 

thanks in advance for helpin' a perl neophyte!

 
Matt Evans

tchrist@convex.COM (Tom Christiansen) (05/23/91)

From the keyboard of matt@snave.Eng.Sun.COM (Matt Evans):
:=======================
: 1) caller command:
:=======================
:   PERL core dumps on the following 
:   code:
:
:
:#!/usr/local/bin/perl
:#---------------------------
:# start test (caller) main
:#---------------------------
:
:   $prog_dir = "./";
:   $prog_name = "not_here";
:
:
:   open (ERR_LOG,">./perr");
:
:   $proc_name = join ("",$prog_dir,$prog_name);

[just side note: this seems is a less obvious method (and more work) than]

	$proc_name = $proc_dir . $prog_name;
or
        $proc_name = "$proc_dir/$prog_name";

:   if (!( -e $conv_proc_name)) {

Warning: this variable was never defined.  stat()ing a null may count
as ".", but then again, maybe not.  On my system, it depends on whether
you compile in posix or traditional mode.

:    # after debugging the core file, it seems perl
:    # dies on the next line
:
:    ($pack,$file,$line,$sub_name) = caller (0);

Debugging the core file?  My, you *were* seriously curious!

I get the same behavior.  Using just caller with no args, or
caller(1), makes it work.  Sounds like a bug for Larry (or
other ambitious volunteers.)

:================================
: 2) numeric & string equalities
:================================
:
: In reading the camel book, it seems there should be no problem
: in comparing strings and numbers, However the behavior of the 
: following perl code seems inconsistent:
:
:
:#!/asdf/bin/perl
:
: $x = "test";
: if ($x == 0) {
:    print "x is equal to 0\n";
: }
: if ($x eq "test") {
:    print "x is equal to the str \"test\"\n";
: }
:
: ------------------------------------------
:
: output:
:
: x is equal to 0
: x is equal to the str "test"
:
:
: Question: Why does $x compare equally to numeric 0? Is this
:	   correct behavior?

$x evaluates to numeric 0, all right.  That's because *numerically*
the string "test" is 0, as are nearly all other strings, except
things like "-1", "1e8", etc.  awk behaves the same way.

:================================
: 3) tom christiansen's open2.pl
:================================
:
: This is more of a question and a FYI. I was using the open2.pl
: routine to fire off a process from perl. The routine works
: like a champ, but it has an interesting side effect. This side
: effect actually occurs in the spawned process. The spawned
: process I was running does an fstat on STDIN to tell if it
: has been started interactively from a terminal  or if it
: has been spawned using pipes. (this C program does many things
: differently based on whether it is started from pipes or
: a character device).
:
:   C code snipit:
:
:     if ((sbuf.st_mode & S_IFMT) == S_IFCHR) {
:        input_term = TRUE;
:     }
:     else {
:           input_term = FALSE;
:     }
:
: well, if the process is started from perl using open2.pl the
: process thinks it was started from a terminal i.e from above
: the var input_term is assigned to TRUE.

Oh REALLY?  I can't repro this puppy.  Here's my C code:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    main() {
	struct stat sb;
	if (fstat(fileno(stdin),&sb) < 0) {
	    perror("fstat");
	    exit(1);
	} 
	if ((sb.st_mode & S_IFMT) == S_IFCHR) {
	    fprintf(stderr, "stdin is a character device\n");
	} else {
	    fprintf(stderr, "stdin is NOT a character device\n");
	} 
    } 

and I invoke it from perl this way:

    require 'open2.pl';
    &open2('IN_HANDLE', 'OUT_HANDLE', "a.out");
    wait;
    exit $?;

On my system, it says that stdin is NOT a character device, which makes
sense, since it's reading from a pipe.  Does yours say otherwise?

However, I'd rather use isatty(fileno(stdin))) to figure out if it's 
a terminal device or not.  That way it won't be fooled by running
something like

    program < /dev/null


--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
		"So much mail, so little time." 

lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) (05/23/91)

In article <1991May23.020207.12967@convex.com> tchrist@convex.COM (Tom Christiansen) writes:
: From the keyboard of matt@snave.Eng.Sun.COM (Matt Evans):
: :=======================
: : 1) caller command:
: :=======================
: :   PERL core dumps on the following 
: :   code:
: :    ($pack,$file,$line,$sub_name) = caller (0);
: 
: I get the same behavior.  Using just caller with no args, or
: caller(1), makes it work.  Sounds like a bug for Larry (or
: other ambitious volunteers.)

I fixed that one several weeks ago.  As a workaround, run your script under
the debugger.

: :================================
: : 2) numeric & string equalities
: :================================
: :
: : In reading the camel book, it seems there should be no problem
: : in comparing strings and numbers, However the behavior of the 
: : following perl code seems inconsistent:
: :
: :
: :#!/asdf/bin/perl
: :
: : $x = "test";
: : if ($x == 0) {
: :    print "x is equal to 0\n";
: : }
: : if ($x eq "test") {
: :    print "x is equal to the str \"test\"\n";
: : }
: :
: : ------------------------------------------
: :
: : output:
: :
: : x is equal to 0
: : x is equal to the str "test"
: :
: :
: : Question: Why does $x compare equally to numeric 0? Is this
: :	   correct behavior?
: 
: $x evaluates to numeric 0, all right.  That's because *numerically*
: the string "test" is 0, as are nearly all other strings, except
: things like "-1", "1e8", etc.  awk behaves the same way.

"test" seems more equal to 0 than to any other number...

: :================================
: : 3) tom christiansen's open2.pl
: :================================
: :
: : This is more of a question and a FYI. I was using the open2.pl
: : routine to fire off a process from perl. The routine works
: : like a champ, but it has an interesting side effect. This side
: : effect actually occurs in the spawned process. The spawned
: : process I was running does an fstat on STDIN to tell if it
: : has been started interactively from a terminal  or if it
: : has been spawned using pipes. (this C program does many things
: : differently based on whether it is started from pipes or
: : a character device).
: :
: :   C code snipit:
: :
: :     if ((sbuf.st_mode & S_IFMT) == S_IFCHR) {
: :        input_term = TRUE;
: :     }
: :     else {
: :           input_term = FALSE;
: :     }
: :
: : well, if the process is started from perl using open2.pl the
: : process thinks it was started from a terminal i.e from above
: : the var input_term is assigned to TRUE.

In general, what an OS puts into the stat structure for a pipe is
kinda hit or miss.  You may have some funny remnants of however dup2()
is implemented.  I wouldn't trust st_mode too far on pipes.  Maybe
you should check some of the other fields first.  If your pipes are
implemented as anonymous FIFO's you should be able to tell from st_dev
and st_ino, I think, or maybe st_nlink.  Happy hunting.

Larry

rich@starnet.uucp (Richard Mahn) (05/24/91)

In <13850@exodus.Eng.Sun.COM> matt@snave.Eng.Sun.COM (Matt Evans) writes:
>=======================
> 1) caller command:
>=======================
>
>   PERL core dumps on the following 
>   code:
>
the problem occurs when there are arguments to the
subroutine caller is referring to.  In other words
if the routine was called by &DO_SOMETHING no problems,
if it was called by &DO_SOMETHING(1) core crashes.  One
solution is to run under debug.  Then it works.  You could
also wait until patch 4.  If you're really in a hurry,
the following patch keeps it from crashing, but you don't
get the argument values.  Larry said he'll have it working
completely in patch 4.

*** dolist.c    Fri May 10 10:20:58 1991
--- dolist.c.orig       Wed May  1 09:34:25 1991
***************
*** 1590,1596 ****
        str_2mortal(str_nmake((double)csv->hasargs)) );
      (void)astore(stack,++sp,
        str_2mortal(str_nmake((double)csv->wantarray)) );
!     if (perldb && csv->hasargs) {
        ARRAY *ary = csv->argarray;
  
        if (dbargs->ary_max < ary->ary_fill)
--- 1590,1596 ----
        str_2mortal(str_nmake((double)csv->hasargs)) );
      (void)astore(stack,++sp,
        str_2mortal(str_nmake((double)csv->wantarray)) );
!     if (csv->hasargs) {
        ARRAY *ary = csv->argarray;
  
        if (dbargs->ary_max < ary->ary_fill)


-----
		Richard Mahn
		Starnet Connections
		rich@starnet.uucp
		apple!starnet!rich