- Continued on the new C parser.
- More reorganizations and fixes.
- API files update.
diff --git a/tools/winapi/c_parser.pm b/tools/winapi/c_parser.pm
index 957723a..87c880c 100644
--- a/tools/winapi/c_parser.pm
+++ b/tools/winapi/c_parser.pm
@@ -2,92 +2,218 @@
use strict;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+require Exporter;
+
+@ISA = qw(Exporter);
+@EXPORT = qw();
+@EXPORT_OK = qw();
+
use options qw($options);
use output qw($output);
-sub _update_c_position {
- local $_ = shift;
- my $refline = shift;
- my $refcolumn = shift;
+use c_function;
- my $line = $$refline;
- my $column = $$refcolumn;
+########################################################################
+# new
+#
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ bless ($self, $class);
- while($_) {
- if(s/^[^\n\t\'\"]*//s) {
- $column += length($&);
- }
+ my $file = \${$self->{FILE}};
+ my $found_comment = \${$self->{FOUND_COMMENT}};
+ my $found_declaration = \${$self->{FOUND_DECLARATION}};
+ my $create_function = \${$self->{CREATE_FUNCTION}};
+ my $found_function = \${$self->{FOUND_FUNCTION}};
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+ my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
+ my $found_statement = \${$self->{FOUND_STATEMENT}};
+ my $found_variable = \${$self->{FOUND_VARIABLE}};
- if(s/^\'//) {
- $column++;
- while(/^./ && !s/^\'//) {
- s/^([^\'\\]*)//s;
- $column += length($1);
- if(s/^\\//) {
- $column++;
- if(s/^(.)//s) {
- $column += length($1);
- if($1 eq "0") {
- s/^(\d{0,3})//s;
- $column += length($1);
- }
- }
- }
- }
- $column++;
- } elsif(s/^\"//) {
- $column++;
- while(/^./ && !s/^\"//) {
- s/^([^\"\\]*)//s;
- $column += length($1);
- if(s/^\\//) {
- $column++;
- if(s/^(.)//s) {
- $column += length($1);
- if($1 eq "0") {
- s/^(\d{0,3})//s;
- $column += length($1);
- }
- }
- }
- }
- $column++;
- } elsif(s/^\n//) {
- $line++;
- $column = 0;
- } elsif(s/^\t//) {
- $column = $column + 8 - $column % 8;
- }
- }
+ $$file = shift;
- $$refline = $line;
- $$refcolumn = $column;
+ $$found_comment = sub { return 1; };
+ $$found_declaration = sub { return 1; };
+ $$create_function = sub { return new c_function; };
+ $$found_function = sub { return 1; };
+ $$found_function_call = sub { return 1; };
+ $$found_preprocessor = sub { return 1; };
+ $$found_statement = sub { return 1; };
+ $$found_variable = sub { return 1; };
+
+ return $self;
}
-sub parse_c {
+########################################################################
+# set_found_comment_callback
+#
+sub set_found_comment_callback {
+ my $self = shift;
+
+ my $found_comment = \${$self->{FOUND_COMMENT}};
+
+ $$found_comment = shift;
+}
+
+########################################################################
+# set_found_declaration_callback
+#
+sub set_found_declaration_callback {
+ my $self = shift;
+
+ my $found_declaration = \${$self->{FOUND_DECLARATION}};
+
+ $$found_declaration = shift;
+}
+
+########################################################################
+# set_found_function_callback
+#
+sub set_found_function_callback {
+ my $self = shift;
+
+ my $found_function = \${$self->{FOUND_FUNCTION}};
+
+ $$found_function = shift;
+}
+
+########################################################################
+# set_found_function_call_callback
+#
+sub set_found_function_call_callback {
+ my $self = shift;
+
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
+ $$found_function_call = shift;
+}
+
+########################################################################
+# set_found_preprocessor_callback
+#
+sub set_found_preprocessor_callback {
+ my $self = shift;
+
+ my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
+
+ $$found_preprocessor = shift;
+}
+
+########################################################################
+# set_found_statement_callback
+#
+sub set_found_statement_callback {
+ my $self = shift;
+
+ my $found_statement = \${$self->{FOUND_STATEMENT}};
+
+ $$found_statement = shift;
+}
+
+########################################################################
+# set_found_variable_callback
+#
+sub set_found_variable_callback {
+ my $self = shift;
+
+ my $found_variable = \${$self->{FOUND_VARIABLE}};
+
+ $$found_variable = shift;
+}
+
+########################################################################
+# _parse_c
+
+sub _parse_c {
+ my $self = shift;
+
my $pattern = shift;
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
+ my $refmatch = shift;
+
local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
- if(s/$pattern//) {
- _update_c_position($&, \$line, \$column);
+ my $match;
+ if(s/^(?:$pattern)//s) {
+ $self->_update_c_position($&, \$line, \$column);
+ $match = $&;
} else {
return 0;
}
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
$$refcurrent = $_;
$$refline = $line;
$$refcolumn = $column;
+ $$refmatch = $match;
+
return 1;
}
-sub parse_c_until_one_of {
+########################################################################
+# _parse_c_error
+
+sub _parse_c_error {
+ my $self = shift;
+
+ my $file = \${$self->{FILE}};
+
+ local $_ = shift;
+ my $line = shift;
+ my $column = shift;
+ my $context = shift;
+
+ my @lines = split(/\n/, $_);
+
+ my $current = "\n";
+ $current .= $lines[0] . "\n" || "";
+ $current .= $lines[1] . "\n" || "";
+
+ if($output->prefix) {
+ $output->write("\n");
+ $output->prefix("");
+ }
+ $output->write("$$file:$line." . ($column + 1) . ": $context: parse error: \\$current");
+
+ exit 1;
+}
+
+########################################################################
+# _parse_c_output
+
+sub _parse_c_output {
+ my $self = shift;
+
+ local $_ = shift;
+ my $line = shift;
+ my $column = shift;
+ my $message = shift;
+
+ my @lines = split(/\n/, $_);
+
+ my $current = "\n";
+ $current .= $lines[0] . "\n" || "";
+ $current .= $lines[1] . "\n" || "";
+
+ $output->write("$line." . ($column + 1) . ": $message: \\$current");
+}
+
+########################################################################
+# _parse_c_until_one_of
+
+sub _parse_c_until_one_of {
+ my $self = shift;
+
my $characters = shift;
my $refcurrent = shift;
my $refline = shift;
@@ -98,11 +224,6 @@
my $line = $$refline;
my $column = $$refcolumn;
- if(!defined($line) || !defined($column)) {
- $output->write("error: \$characters = '$characters' \$_ = '$_'\n");
- exit 1;
- }
-
if(!defined($match)) {
my $blackhole;
$match = \$blackhole;
@@ -179,10 +300,80 @@
return 1;
}
+########################################################################
+# _update_c_position
+
+sub _update_c_position {
+ my $self = shift;
+
+ local $_ = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ while($_) {
+ if(s/^[^\n\t\'\"]*//s) {
+ $column += length($&);
+ }
+
+ if(s/^\'//) {
+ $column++;
+ while(/^./ && !s/^\'//) {
+ s/^([^\'\\]*)//s;
+ $column += length($1);
+ if(s/^\\//) {
+ $column++;
+ if(s/^(.)//s) {
+ $column += length($1);
+ if($1 eq "0") {
+ s/^(\d{0,3})//s;
+ $column += length($1);
+ }
+ }
+ }
+ }
+ $column++;
+ } elsif(s/^\"//) {
+ $column++;
+ while(/^./ && !s/^\"//) {
+ s/^([^\"\\]*)//s;
+ $column += length($1);
+ if(s/^\\//) {
+ $column++;
+ if(s/^(.)//s) {
+ $column += length($1);
+ if($1 eq "0") {
+ s/^(\d{0,3})//s;
+ $column += length($1);
+ }
+ }
+ }
+ }
+ $column++;
+ } elsif(s/^\n//) {
+ $line++;
+ $column = 0;
+ } elsif(s/^\t//) {
+ $column = $column + 8 - $column % 8;
+ }
+ }
+
+ $$refline = $line;
+ $$refcolumn = $column;
+}
+
+########################################################################
+# parse_c_block
+
sub parse_c_block {
+ my $self = shift;
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
+
my $refstatements = shift;
my $refstatements_line = shift;
my $refstatements_column = shift;
@@ -191,6 +382,8 @@
my $line = $$refline;
my $column = $$refcolumn;
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
my $statements;
if(s/^\{//) {
$column++;
@@ -199,7 +392,7 @@
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
my $statements_line = $line;
my $statements_column = $column;
@@ -207,7 +400,7 @@
my $plevel = 1;
while($plevel > 0) {
my $match;
- parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match);
+ $self->_parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match);
$column++;
@@ -235,63 +428,161 @@
return 1;
}
-sub parse_c_expression {
+########################################################################
+# parse_c_declaration
+
+sub parse_c_declaration {
+ my $self = shift;
+
+ my $found_declaration = \${$self->{FOUND_DECLARATION}};
+ my $found_function = \${$self->{FOUND_FUNCTION}};
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
- my $found_function_call_callback = shift;
+ local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ my $end_line = $begin_line;
+ my $end_column = $begin_column;
+ $self->_update_c_position($_, \$end_line, \$end_column);
+
+ if(!&$$found_declaration($begin_line, $begin_column, $end_line, $end_column, $_)) {
+ return 1;
+ }
+
+ # Function
+ my $function = shift;
+
+ my $linkage = shift;
+ my $calling_convention = shift;
+ my $return_type = shift;
+ my $name = shift;
+ my @arguments = shift;
+ my @argument_lines = shift;
+ my @argument_columns = shift;
+
+ # Variable
+ my $type;
+
+ # $self->_parse_c_output($_, $line, $column, "declaration");
+
+ if(0) {
+ # Nothing
+ } elsif(s/^(?:DEFAULT|DECLARE)_DEBUG_CHANNEL\s*\(\s*(\w+)\s*\)\s*//s) { # FIXME: Wine specific kludge
+ $self->_update_c_position($&, \$line, \$column);
+ } elsif(s/^extern\s*\"(.*?)\"\s*//s) {
+ $self->_update_c_position($&, \$line, \$column);
+ my $declarations;
+ my $declarations_line;
+ my $declarations_column;
+ if(!$self->parse_c_block(\$_, \$line, \$column, \$declarations, \$declarations_line, \$declarations_column)) {
+ return 0;
+ }
+ if(!$self->parse_c_declarations(\$declarations, \$declarations_line, \$declarations_column)) {
+ return 0;
+ }
+ } elsif($self->parse_c_function(\$_, \$line, \$column, \$function)) {
+ if(&$$found_function($function))
+ {
+ my $statements = $function->statements;
+ my $statements_line = $function->statements_line;
+ my $statements_column = $function->statements_column;
+
+ if(defined($statements)) {
+ if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
+ return 0;
+ }
+ }
+ }
+ } elsif($self->parse_c_typedef(\$_, \$line, \$column)) {
+ # Nothing
+ } elsif($self->parse_c_variable(\$_, \$line, \$column, \$linkage, \$type, \$name)) {
+ # Nothing
+ } else {
+ $self->_parse_c_error($_, $line, $column, "declaration");
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_declarations
+
+sub parse_c_declarations {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_expression
+
+sub parse_c_expression {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
- if(s/^(.*?)(\w+)(\s*)\(//s) {
+ if(s/^(.*?)(\w+\s*\()/$2/s) {
+ $column += length($1);
+
my $begin_line = $line;
- my $begin_column = $column + length($1) + 1;
+ my $begin_column = $column + 1;
- $line = $begin_line;
- $column = $begin_column + length("$2$3") - 1;
-
- my $name = $2;
-
- $_ = "($'";
-
- # $output->write("$name: $line.$column: '$_'\n");
-
+ my $name;
my @arguments;
my @argument_lines;
my @argument_columns;
- if(!parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ if(!$self->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns)) {
return 0;
}
- if($name =~ /^sizeof$/) {
- # Nothing
- } else {
- &$found_function_call_callback($begin_line, $begin_column, $line, $column,
- $name, \@arguments);
- }
-
- while(defined(my $argument = shift @arguments) &&
- defined(my $argument_line = shift @argument_lines) &&
- defined(my $argument_column = shift @argument_columns))
+ if($name =~ /^sizeof$/ ||
+ &$$found_function_call($begin_line, $begin_column, $line, $column, $name, \@arguments))
{
- parse_c_expression(\$argument, \$argument_line, \$argument_column, $found_function_call_callback);
+ while(defined(my $argument = shift @arguments) &&
+ defined(my $argument_line = shift @argument_lines) &&
+ defined(my $argument_column = shift @argument_columns))
+ {
+ $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
+ }
}
} elsif(s/^return//) {
$column += length($&);
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
- if(!parse_c_expression(\$_, \$line, \$column, $found_function_call_callback)) {
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ if(!$self->parse_c_expression(\$_, \$line, \$column)) {
return 0;
}
} else {
return 0;
}
- _update_c_position($_, \$line, \$column);
+ $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_;
$$refline = $line;
@@ -300,22 +591,358 @@
return 1;
}
-sub parse_c_statement {
+########################################################################
+# parse_c_file
+
+sub parse_c_file {
+ my $self = shift;
+
+ my $found_comment = \${$self->{FOUND_COMMENT}};
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
- my $found_function_call_callback = shift;
-
+
+ local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
- local $_ = $$refcurrent;
+ my $declaration = "";
+ my $declaration_line = $line;
+ my $declaration_column = $column;
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ my $previous_line = 0;
+ my $previous_column = -1;
+
+ my $blevel = 1;
+ my $plevel = 1;
+ while($plevel > 0 || $blevel > 0) {
+ my $match;
+ $self->_parse_c_until_one_of("#/\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
+
+ if($line == $previous_line && $column == $previous_column) {
+ # $self->_parse_c_error($_, $line, $column, "file: no progress");
+ }
+ $previous_line = $line;
+ $previous_column = $column;
+
+ # $self->_parse_c_output($_, $line, $column, "'$match'");
+
+ if(!$declaration && $match =~ s/^\s+//s) {
+ $self->_update_c_position($&, \$declaration_line, \$declaration_column);
+ }
+ $declaration .= $match;
+
+ if(/^[\#\/]/) {
+ my $blank_lines = 0;
+ if(s/^\#\s*//) {
+ my $preprocessor_line = $line;
+ my $preprocessor_column = $column;
+
+ my $preprocessor = $&;
+ while(s/^(.*?)\\\s*\n//) {
+ $blank_lines++;
+ $preprocessor .= "$1\n";
+ }
+ if(s/^(.*?)(\/[\*\/].*)?\n//) {
+ if(defined($2)) {
+ $_ = "$2\n$_";
+ } else {
+ $blank_lines++;
+ }
+ $preprocessor .= $1;
+ }
+
+ if(!$self->parse_c_preprocessor(\$preprocessor, \$preprocessor_line, \$preprocessor_column)) {
+ return 0;
+ }
+ }
+
+ if(s/^\/\*(.*?)\*\///s) {
+ &$$found_comment($line, $column + 1, "/*$1*/");
+ my @lines = split(/\n/, $1);
+ if($#lines > 0) {
+ $blank_lines += $#lines;
+ } else {
+ $column += length($1);
+ }
+ } elsif(s/^\/\/(.*?)\n//) {
+ &$$found_comment($line, $column + 1, "//$1");
+ $blank_lines++;
+ } elsif(s/^\///) {
+ $declaration .= $&;
+ }
+
+ $line += $blank_lines;
+ if($blank_lines > 0) {
+ $column = 0;
+ }
+
+ if(!$declaration) {
+ $declaration_line = $line;
+ $declaration_column = $column;
+ } else {
+ $declaration .= "\n" x $blank_lines;
+ }
+
+ next;
+ }
+
+ $column++;
+ if(s/^[\(\[]//) {
+ $plevel++;
+ $declaration .= $&;
+ } elsif(s/^[\)\]]//) {
+ $plevel--;
+ $declaration .= $&;
+ } elsif(s/^\{//) {
+ $blevel++;
+ $declaration .= $&;
+ } elsif(s/^\}//) {
+ $blevel--;
+ $declaration .= $&;
+ if($plevel == 1 && $blevel == 1 && $declaration !~ /^typedef/) {
+ if(!$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
+ return 0;
+ }
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $declaration = "";
+ $declaration_line = $line;
+ $declaration_column = $column;
+ }
+ } elsif(s/^;//) {
+ if($plevel == 1 && $blevel == 1) {
+ if($declaration && !$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
+ return 0;
+ }
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $declaration = "";
+ $declaration_line = $line;
+ $declaration_column = $column;
+ } else {
+ $declaration .= $&;
+ }
+ } elsif(/^\s*$/ && $declaration =~ /^\s*$/ && $match =~ /^\s*$/) {
+ $plevel = 0;
+ $blevel = 0;
+ } else {
+ $self->_parse_c_error($_, $line, $column, "file");
+ }
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_function
+
+sub parse_c_function {
+ my $self = shift;
+
+ my $file = \${$self->{FILE}};
+ my $create_function = \${$self->{CREATE_FUNCTION}};
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reffunction = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $linkage = "";
+ my $calling_convention = "";
+ my $return_type;
+ my $name;
+ my @arguments;
+ my @argument_lines;
+ my @argument_columns;
+ my $statements;
+ my $statements_line;
+ my $statements_column;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ $self->_parse_c("inline", \$_, \$line, \$column);
+ $self->_parse_c("extern|static", \$_, \$line, \$column, \$linkage);
+ $self->_parse_c("inline", \$_, \$line, \$column);
+ if(!$self->parse_c_type(\$_, \$line, \$column, \$return_type)) {
+ return 0;
+ }
+
+ $self->_parse_c("__cdecl|__stdcall|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK",
+ \$_, \$line, \$column, \$calling_convention);
+ if(!$self->_parse_c("\\w+", \$_, \$line, \$column, \$name)) {
+ return 0;
+ }
+ if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ return 0;
+ }
+ if($_ && !$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
+ return 0;
+ }
+
+ my $end_line = $line;
+ my $end_column = $column;
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ my $function = &$$create_function;
+
+ $function->file($$file);
+ $function->begin_line($begin_line);
+ $function->begin_column($begin_column);
+ $function->end_line($end_line);
+ $function->end_column($end_column);
+ $function->linkage($linkage);
+ $function->return_type($return_type);
+ $function->calling_convention($calling_convention);
+ $function->name($name);
+ # if(defined($argument_types)) {
+ # $function->argument_types([@$argument_types]);
+ # }
+ # if(defined($argument_names)) {
+ # $function->argument_names([@$argument_names]);
+ # }
+ $function->statements_line($statements_line);
+ $function->statements_column($statements_column);
+ $function->statements($statements);
+
+ $$reffunction = $function;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_function_call
+
+sub parse_c_function_call {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $refname = shift;
+ my $refarguments = shift;
+ my $refargument_lines = shift;
+ my $refargument_columns = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $name;
+ my @arguments;
+ my @argument_lines;
+ my @argument_columns;
+
+ if(s/^(\w+)(\s*)\(/\(/s) {
+ $column += length("$1$2");
+
+ $name = $1;
+
+ if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$refname = $name;
+ @$refarguments = @arguments;
+ @$refargument_lines = @argument_lines;
+ @$refargument_columns = @argument_columns;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_preprocessor
+
+sub parse_c_preprocessor {
+ my $self = shift;
+
+ my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ if(!&$$found_preprocessor($begin_line, $begin_column, "$_")) {
+ return 1;
+ }
+
+ if(0) {
+ # Nothing
+ } elsif(/^\#\s*define\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*else/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*endif/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*(?:if|ifdef|ifndef)?\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*include\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } elsif(/^\#\s*undef\s+(.*?)$/s) {
+ $self->_update_c_position($_, \$line, \$column);
+ } else {
+ $self->_parse_c_error($_, $line, $column, "preprocessor");
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_statement
+
+sub parse_c_statement {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
if(s/^(?:case\s+)?(\w+)\s*://) {
$column += length($&);
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
}
# $output->write("$line.$column: '$_'\n");
@@ -326,10 +953,10 @@
my $statements;
my $statements_line;
my $statements_column;
- if(!parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
+ if(!$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
return 0;
}
- if(!parse_c_statements(\$statements, \$statements_line, \$statements_column, $found_function_call_callback)) {
+ if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
return 0;
}
} elsif(/^(for|if|switch|while)(\s*)\(/) {
@@ -341,35 +968,34 @@
my @arguments;
my @argument_lines;
my @argument_columns;
- if(!parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
+ if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
- if(!parse_c_statement(\$_, \$line, \$column, $found_function_call_callback)) {
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ if(!$self->parse_c_statement(\$_, \$line, \$column)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
while(defined(my $argument = shift @arguments) &&
defined(my $argument_line = shift @argument_lines) &&
defined(my $argument_column = shift @argument_columns))
{
- parse_c_expression(\$argument, \$argument_line, \$argument_column, $found_function_call_callback);
+ $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
}
} elsif(s/^else//) {
$column += length($&);
- if(!parse_c_statement(\$_, \$line, \$column, $found_function_call_callback)) {
+ if(!$self->parse_c_statement(\$_, \$line, \$column)) {
return 0;
}
- } elsif(parse_c_expression(\$_, \$line, \$column, $found_function_call_callback)) {
+ } elsif($self->parse_c_expression(\$_, \$line, \$column)) {
# Nothing
} else {
- # $output->write("error '$_'\n");
- # exit 1;
+ # $self->_parse_c_error($_, $line, $column, "statement");
}
- _update_c_position($_, \$line, \$column);
+ $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_;
$$refline = $line;
@@ -378,18 +1004,24 @@
return 1;
}
+########################################################################
+# parse_c_statements
+
sub parse_c_statements {
+ my $self = shift;
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
- my $found_function_call_callback = shift;
+ my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
+
+ local $_ = $$refcurrent;
my $line = $$refline;
my $column = $$refcolumn;
- local $_ = $$refcurrent;
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
my $statement = "";
my $statement_line = $line;
my $statement_column = $column;
@@ -398,7 +1030,7 @@
my $plevel = 1;
while($plevel > 0 || $blevel > 0) {
my $match;
- parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
+ $self->_parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
# $output->write("'$match' '$_'\n");
@@ -410,8 +1042,7 @@
} elsif(s/^[\)\]]//) {
$plevel--;
if($plevel <= 0) {
- $output->write("error $plevel: '$statement' '$match' '$_'\n");
- exit 1;
+ $self->_parse_c_error($_, $line, $column, "statements");
}
$statement .= $&;
} elsif(s/^\{//) {
@@ -421,21 +1052,21 @@
$blevel--;
$statement .= $&;
if($blevel == 1) {
- if(!parse_c_statement(\$statement, \$statement_line, \$statement_column, $found_function_call_callback)) {
+ if(!$self->parse_c_statement(\$statement, \$statement_line, \$statement_column)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$statement = "";
$statement_line = $line;
$statement_column = $column;
}
} elsif(s/^;//) {
if($plevel == 1 && $blevel == 1) {
- if(!parse_c_statement(\$statement, \$statement_line, \$statement_column, $found_function_call_callback)) {
+ if(!$self->parse_c_statement(\$statement, \$statement_line, \$statement_column)) {
return 0;
}
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$statement = "";
$statement_line = $line;
$statement_column = $column;
@@ -446,12 +1077,11 @@
$plevel = 0;
$blevel = 0;
} else {
- $output->write("error $plevel: '$statement' '$match' '$_'\n");
- exit 1;
+ $self->_parse_c_error($_, $line, $column, "statements");
}
}
- _update_c_position($_, \$line, \$column);
+ $self->_update_c_position($_, \$line, \$column);
$$refcurrent = $_;
$$refline = $line;
@@ -460,7 +1090,12 @@
return 1;
}
+########################################################################
+# parse_c_tuple
+
sub parse_c_tuple {
+ my $self = shift;
+
my $refcurrent = shift;
my $refline = shift;
my $refcolumn = shift;
@@ -489,7 +1124,7 @@
my $plevel = 1;
while($plevel > 0) {
my $match;
- parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match);
+ $self->_parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match);
$column++;
@@ -512,7 +1147,7 @@
push @$item_lines, $item_line;
push @$item_columns, $item_column;
push @$items, $item;
- parse_c_until_one_of("\\S", \$_, \$line, \$column);
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
$item_line = $line;
$item_column = $column + 1;
$item = "";
@@ -531,4 +1166,125 @@
return 1;
}
+########################################################################
+# parse_c_type
+
+sub parse_c_type {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reftype = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $type;
+
+ $self->_parse_c("const", \$_, \$line, \$column);
+
+
+ if(0) {
+ # Nothing
+ } elsif($self->_parse_c('ICOM_VTABLE\(.*?\)', \$_, \$line, \$column, \$type)) {
+ # Nothing
+ } elsif($self->_parse_c('\w+\s*(\*\s*)*', \$_, \$line, \$column, \$type)) {
+ # Nothing
+ } else {
+ return 0;
+ }
+ $type =~ s/\s//g;
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$reftype = $type;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_typedef
+
+sub parse_c_typedef {
+ my $self = shift;
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reftype = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ my $type;
+
+ if(!$self->_parse_c("typedef", \$_, \$line, \$column)) {
+ return 0;
+ }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$reftype = $type;
+
+ return 1;
+}
+
+########################################################################
+# parse_c_variable
+
+sub parse_c_variable {
+ my $self = shift;
+
+ my $found_variable = \${$self->{FOUND_VARIABLE}};
+
+ my $refcurrent = shift;
+ my $refline = shift;
+ my $refcolumn = shift;
+
+ my $reflinkage = shift;
+ my $reftype = shift;
+ my $refname = shift;
+
+ local $_ = $$refcurrent;
+ my $line = $$refline;
+ my $column = $$refcolumn;
+
+ $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
+
+ my $begin_line = $line;
+ my $begin_column = $column + 1;
+
+ my $linkage = "";
+ my $type;
+ my $name;
+
+ $self->_parse_c("extern|static", \$_, \$line, \$column, \$linkage);
+ if(!$self->parse_c_type(\$_, \$line, \$column, \$type)) { return 0; }
+ if(!$self->_parse_c("\\w+", \$_, \$line, \$column, \$name)) { return 0; }
+
+ $$refcurrent = $_;
+ $$refline = $line;
+ $$refcolumn = $column;
+
+ $$reflinkage = $linkage;
+ $$reftype = $type;
+ $$refname = $name;
+
+ if(&$$found_variable($begin_line, $begin_column, $linkage, $type, $name))
+ {
+ # Nothing
+ }
+
+ return 1;
+}
+
1;