Invalid Argument while Opening file

P

Pradeep

Hi all,
When I was writing a code which will check some syntax of the files
inside a directory. The first_pass proc gathers all the related
variables and second_pass proc process those lines inside the file.
When I ran the program it gave an error:
Couldn't open input file "a.tcl": Invalid argument at C:/qtcheckref/
checktclvars.pl line 268, <INFILE> line 13591.

Could anyone help me in this regard?


$ignoreArrays = " $ignoreArrays";
$varNames = " argv $ignoreVars";

@files = ();

# Do the actual work
#
while ($file = shift())
{
push @files,$file;
}

#
# Run the first pass - collect variable names
#
@temp = @files;
while ($file = shift(@temp))
{
$varNames = first_pass($file,$varNames);
}

#
# Run the second pass - check variable names
#
@temp = @files;
while ($file = shift(@temp))
{
while (<$file>)
{
print "Checking $_\n";
second_pass( $_ , $varNames );
}
}

#--------------------------------------------------------------------------

#
# Add_Var:
# Add to the list of known variables
#
# parameters:
# $_[0] - variable to add
# $_[1] - list of known variables so far
#
# returns:
# The new list of known variables
#
sub add_var {
my $var = $_[0];
my $vars = $_[1];

$pattern = $var;
$pattern =~ s/\)/\\\)/;
$pattern =~ s/\(/\\\(/;

if ($vars !~ / $pattern/)
{
$vars = "$vars $var";
}

return $vars;
}

#
# First pass:
# Pass over the file, and collect variable definitions.
# Note: We ignore variable names with '$'s in them,
# or variable names with [set xxx] in them.
#
# When arrays are found, collect the name of the array.
# Also collect the element of the array
# if the array index has no weird shit in it.
#
# parameters:
# $_[0] - filename
# $_[1] - list of known variables so far
#
sub first_pass {
my $infile = $_[0];
my $vars = $_[1];
my $array, $var, $temp, $key;

open(INFILE,"<$infile")
|| die "Couldn't open input file '$infile': $!";

while (<INFILE>)
{
$line = $_;

# strip comments
$line =~ s/^\s*(\#.*)//;
$line =~ s/;(\#.*)//;

# Check for continuing line ('\' at end)
while ( $line =~ /\\\s*$/ )
{
# strip the tailing '\' and newline
$line =~ s/\\.*$//s;
$nextLine = <INFILE>;

$line = "$line $nextLine";

# Now re-strip comments
$line =~ s/^\s*(\#.*)//;
$line =~ s/;(\#.*)//;
}


# Look for statements of the form "set a b" (or "set
namespace::a b")
while ( $line =~ /set\s+(\w*::)?(\w+)/g )
{
$vars = add_var($2, $vars);
# if this is an array element, we've already got the name
of the array.
# see if we can get the element of the array also.
if ( $line =~ /set\s+(\w+\(\w+\))/ )
{
$vars = add_var($1, $vars);
}
}

# Look for statements of the form "foreach a ..."
if ($line =~ s/foreach\s+//)
{
# match "foreach a $b" and "foreach a $b c $d"
while ($line =~ /\{?(\w+)\}?\s+\S+/g)
{
$vars = add_var($1, $vars);
}
}

# Look for statements of the form "gets channelId varName"
if ($line =~ s/gets\s+\S+\s+(\w+)//)
{
$vars = add_var($1, $vars);
}

# Look for statements of the form "lappend varName values"
if ($line =~ s/lappend\s+(\w+)//)
{
$vars = add_var($1, $vars);
}

# Look for statements of the form "global a"
if ($line =~ /global\s+(\w+)/)
{
$vars = add_var($1, $vars);
}

# Look for statements of the form "catch { ... } var"
if ($line =~ /catch\s+(\{[^\}]+\}|\"[^\"]+\")\s+(\w+)/)
{
$vars = add_var($2, $vars);
}

# Look for statements of the form "proc .... { varname1
varname2 } {"
if ( $line =~ /^proc/ ) {
$line =~ s/^proc [^\{]+\{\s*//;

while ($line =~ /((\w|_)+)\W+/g)
{
$vars = add_var($1, $vars);
}
}

# Look for statements of the form "array set arrayName
[list ...
if ( $line =~ /\s*array\s+set\s+(\w+)\s+\[\s*list/ )
{
$array = $1;
$temp = $line;

# strip off the crap at the front
$temp =~ s/\s*array\s+set\s+\w+\s+\[\s*list\s*//;

# look for elements being defined (ie. 'key value' pairs)
while ( $temp =~ /((\[[^\]]\]|\S+)+)\s+(\{[^\}]+\}|\"[^\"]+
\"|\[[^\]]+\]|\S+)+/g )
{
$key = $1;

# only add it if there's no weird shit
if ($key =~ /\w+/)
{
$var = "$array($key)";
$vars = add_var($var, $vars);
}
}
}
}
return $vars;

close(INFILE);
}

#
# Second pass:
# Pass over the file, looking for:
# - undefined variables
# - 'set $varname value' style errors
# - 'foreach $varname list' style errors
#
# parameters:
# $_[0] - filename
# $_[1] - the list of known variables
#
# returns:
# nothing
#
sub second_pass {
my $infile = $_[0];
my $vars = $_[1];
my $lineNum = 0;
my $array, $var, $pattern, $suggest;

open(INFILE,"<$infile")
|| die "Couldn't open input file $infile: $!";

while (<INFILE>)
{
$line = $_;
$lineNum++;

# strip comments
$line =~ s/^\s*\#.*//;
$line =~ s/;\#.*//;

# Check for continuing line ('\' at end)
while ( $line =~ /\\\s*$/ )
{
$lineNum++;

# strip the tailing '\' and newline
$line =~ s/\\.*$//s;
 
J

John W. Krahn

Pradeep said:
When I was writing a code which will check some syntax of the files
inside a directory. The first_pass proc gathers all the related
variables and second_pass proc process those lines inside the file.
When I ran the program it gave an error:
Couldn't open input file "a.tcl": Invalid argument at C:/qtcheckref/
checktclvars.pl line 268, <INFILE> line 13591.

Could anyone help me in this regard?


$ignoreArrays = " $ignoreArrays";
$varNames = " argv $ignoreVars";

@files = ();

# Do the actual work
#
while ($file = shift())
{
push @files,$file;
}

Or simply:

my @files = @ARGV;

#
# Run the first pass - collect variable names
#
@temp = @files;
while ($file = shift(@temp))
{
$varNames = first_pass($file,$varNames);
}

If you have a file named "0" your loop will end.

foreach my $file ( @files ) {
$varNames = first_pass( $file, $varNames );
}

#
# Run the second pass - check variable names
#
@temp = @files;
while ($file = shift(@temp))
{
while (<$file>)

You are trying to read lines from the filehandle $file but $file
contains the *name* of a file, not a filehandle.

{
print "Checking $_\n";
second_pass( $_ , $varNames );
}
}

foreach my $file ( @files ) {
print "Checking $file\n";
second_pass( $file, $varNames );
}

#--------------------------------------------------------------------------

#
# Add_Var:
# Add to the list of known variables
#
# parameters:
# $_[0] - variable to add
# $_[1] - list of known variables so far
#
# returns:
# The new list of known variables
#
sub add_var {
my $var = $_[0];
my $vars = $_[1];

$pattern = $var;
$pattern =~ s/\)/\\\)/;
$pattern =~ s/\(/\\\(/;

if ($vars !~ / $pattern/)
{
$vars = "$vars $var";
}

return $vars;
}

Or simply:

sub add_var {
my ( $var, $vars ) = @_;

if ($vars !~ / \Q$var/)
{
$vars .= " $var";
}

return $vars;
}

#
# First pass:
# Pass over the file, and collect variable definitions.
# Note: We ignore variable names with '$'s in them,
# or variable names with [set xxx] in them.
#
# When arrays are found, collect the name of the array.
# Also collect the element of the array
# if the array index has no weird shit in it.
#
# parameters:
# $_[0] - filename
# $_[1] - list of known variables so far
#
sub first_pass {
my $infile = $_[0];
my $vars = $_[1];
my $array, $var, $temp, $key;

open(INFILE,"<$infile")
|| die "Couldn't open input file '$infile': $!";

while (<INFILE>)
{
$line = $_;

# strip comments
$line =~ s/^\s*(\#.*)//;
$line =~ s/;(\#.*)//;

# Check for continuing line ('\' at end)
while ( $line =~ /\\\s*$/ )
{
# strip the tailing '\' and newline
$line =~ s/\\.*$//s;
$nextLine = <INFILE>;

$line = "$line $nextLine";

# Now re-strip comments
$line =~ s/^\s*(\#.*)//;
$line =~ s/;(\#.*)//;
}

while (my $line = <INFILE>)
{
# strip comments
$line =~ s/^\s*(#.*)//;
$line =~ s/;(#.*)//;

# Check for continuing line ('\' at end)
if ( $line =~ s/\\\s*\n\z// )
{
$line .= ' ' . <INFILE>;

# Now re-strip comments
redo;
}



John
 
T

Tad J McClellan

Pradeep said:
Couldn't open input file "a.tcl": Invalid argument at C:/qtcheckref/ ^ ^
checktclvars.pl line 268, <INFILE> line 13591.
open(INFILE,"<$infile")
|| die "Couldn't open input file '$infile': $!";
^ ^

It appears that you have a corrupted install of perl itself, as it is
somehow converting single quotes into double quotes...

Is the code above "line 268"?

....

open(INFILE,"<$infile")
|| die "Couldn't open input file $infile: $!";


.... or is this "line 268"?


Now it appears that the corruption is *inserting* double quote characters...
 
T

Tad J McClellan

Pradeep said:
@files = ();

# Do the actual work
#
while ($file = shift())
{
push @files,$file;
}


@files = @ARGV; # replace all of the above with a single copy


Note that @files contains filenames (strings).

while ($file = shift(@temp))
{
$varNames = first_pass($file,$varNames);
}


Are you familiar with the "foreach" control structure?

You should be...

See the "Foreach Loops" in perlsyn.pod

@temp = @files;


Note that @temp also contains filenames (strings).

while ($file = shift(@temp))


Note that $file also contains a filename (string).

{
while (<$file>)


You should always enable warnings when developing Perl code!

The input operator takes a filehandle not a filename.

sub add_var {
my $var = $_[0];
my $vars = $_[1];


my( $var, $vars ) = @_; # a better way of copying arguments

$pattern =~ s/\)/\\\)/;


The 2nd (replacement) part of s/// is not a regular expression, it
is a double quotish string.

Parenthesis are not meta in double quoted strings, so you have
more backslashes than you need:

$pattern =~ s/\)/\\)/;

while (<INFILE>)
{
$line = $_;


If you want the input line in $line, then why put it somewhere else then
copy it rather than simply put it where you want it when you first get it?


$line =~ s/^\s*(\#.*)//;


Number signs are not meta in regular expressions. You have more
backslashes than you need.

You should not capture if you are not going to use the string
that is captured...


$line =~ s/^\s*#.*//;

while ( $line =~ /\\\s*$/ )
{
# strip the tailing '\' and newline
$line =~ s/\\.*$//s;


Note that this pattern is not the same as the pattern in the while()...

It will change

I have a backslash in the \middle and at the end too\

into

I have a backslash in the

You can use s/// in the while condition you know:

while ( $line =~ s/\\\s*$// )

$line = "$line $nextLine";


Same as

$line .= " $nextLine";

while ($line =~ /((\w|_)+)\W+/g)


Same as

while ($line =~ /(\w+)\W+/g)

since \w already contains underscore.
 
S

smallpond

Hi all,
When I was writing a code which will check some syntax of the files
inside a directory. The first_pass proc gathers all the related
variables and second_pass proc process those lines inside the file.
When I ran the program it gave an error:
Couldn't open input file "a.tcl": Invalid argument at C:/qtcheckref/
checktclvars.pl line 268, <INFILE> line 13591.

Could anyone help me in this regard?

return $vars;

close(INFILE);

How do you get to the close statement?
 
R

Randal L. Schwartz

Pradeep> my $array, $var, $temp, $key;

use strict and/or use warnings would have both caught this error.

Clearly, you're not using either, despite all the tutorials that
say to do so.

Why don't you start there, and when you fix everything they point out,
come back here?

print "Just another Perl hacker,"; # the original
 
X

xhoster

Pradeep said:
Hi all,
When I was writing a code which will check some syntax of the files
inside a directory. The first_pass proc gathers all the related
variables and second_pass proc process those lines inside the file.
When I ran the program it gave an error:
Couldn't open input file "a.tcl": Invalid argument at C:/qtcheckref/
checktclvars.pl line 268, <INFILE> line 13591.

Could anyone help me in this regard?

If you are going to post 235 lines of code (and not even have that code
be complete at 268 lines), which you really shouldn't do, then you should
at least tell us which of those lines corresponds to line 268 of your
original code.
open(INFILE,"<$infile")
|| die "Couldn't open input file '$infile': $!";

If you accurately reported the error message, then the absence of literal
single quotes suggests that this is not line 268.

....
open(INFILE,"<$infile")
|| die "Couldn't open input file $infile: $!";

If you accurately reported the error message, and if this is line 268,
then the value of the variable $infile seems to contain literal double
quotes in it, as if the name of the file included quote symbols. On
windows, this apparently is not allowed.


Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
S

smallpond

Hi all,
When I was writing a code which will check some syntax of the files
inside a directory. The first_pass proc gathers all the related
variables and second_pass proc process those lines inside the file.
When I ran the program it gave an error:
Couldn't open input file "a.tcl":
^^^^^

Now I realize what your program is for. You are using perl
to check syntax of tcl files. That's like using a Ferrari to
tow your Corvair. Just convert all your code to perl and you
won't have to do this code at all.

To check the syntax of perl code:

perl -c myperlcode
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top