2 # Copyright 1999, 2000, 2001 Patrik Stridvall
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 use vars
qw($VERSION @ISA @EXPORT @EXPORT_OK);
30 use options
qw($options);
31 use output qw($output);
35 ########################################################################
40 my $class = ref($proto) || $proto;
42 bless ($self, $class);
44 my $file = \${$self->{FILE}};
45 my $found_comment = \${$self->{FOUND_COMMENT}};
46 my $found_declaration = \${$self->{FOUND_DECLARATION}};
47 my $create_function = \${$self->{CREATE_FUNCTION}};
48 my $found_function = \${$self->{FOUND_FUNCTION}};
49 my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
50 my $found_line = \${$self->{FOUND_LINE}};
51 my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
52 my $found_statement = \${$self->{FOUND_STATEMENT}};
53 my $found_variable = \${$self->{FOUND_VARIABLE}};
57 $$found_comment = sub { return 1; };
58 $$found_declaration = sub { return 1; };
59 $$create_function = sub { return new c_function; };
60 $$found_function = sub { return 1; };
61 $$found_function_call = sub { return 1; };
62 $$found_line = sub { return 1; };
63 $$found_preprocessor = sub { return 1; };
64 $$found_statement = sub { return 1; };
65 $$found_variable = sub { return 1; };
70 ########################################################################
71 # set_found_comment_callback
73 sub set_found_comment_callback {
76 my $found_comment = \${$self->{FOUND_COMMENT}};
78 $$found_comment = shift;
81 ########################################################################
82 # set_found_declaration_callback
84 sub set_found_declaration_callback {
87 my $found_declaration = \${$self->{FOUND_DECLARATION}};
89 $$found_declaration = shift;
92 ########################################################################
93 # set_found_function_callback
95 sub set_found_function_callback {
98 my $found_function = \${$self->{FOUND_FUNCTION}};
100 $$found_function = shift;
103 ########################################################################
104 # set_found_function_call_callback
106 sub set_found_function_call_callback {
109 my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
111 $$found_function_call = shift;
114 ########################################################################
115 # set_found_line_callback
117 sub set_found_line_callback {
120 my $found_line = \${$self->{FOUND_LINE}};
122 $$found_line = shift;
125 ########################################################################
126 # set_found_preprocessor_callback
128 sub set_found_preprocessor_callback {
131 my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
133 $$found_preprocessor = shift;
136 ########################################################################
137 # set_found_statement_callback
139 sub set_found_statement_callback {
142 my $found_statement = \${$self->{FOUND_STATEMENT}};
144 $$found_statement = shift;
147 ########################################################################
148 # set_found_variable_callback
150 sub set_found_variable_callback {
153 my $found_variable = \${$self->{FOUND_VARIABLE}};
155 $$found_variable = shift;
158 ########################################################################
165 my $refcurrent = shift;
167 my $refcolumn = shift;
169 my $refmatch = shift;
171 local $_ = $$refcurrent;
172 my $line = $$refline;
173 my $column = $$refcolumn;
176 if(s/^(?:$pattern)//s) {
177 $self->_update_c_position($&, \$line, \$column);
183 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
187 $$refcolumn = $column;
194 ########################################################################
197 # FIXME: Use caller (See man perlfunc)
202 my $file = \${$self->{FILE}};
210 $message = "parse error" if !$message;
214 my @lines = split(/\n/, $_);
216 $current .= $lines[0] . "\n" if $lines[0];
217 $current .= $lines[1] . "\n" if $lines[1];
220 if($output->prefix) {
221 $output->write("\n");
226 $output->write("$$file:$line." . ($column + 1) . ": $context: $message: \\\n$current");
228 $output->write("$$file:$line." . ($column + 1) . ": $context: $message\n");
234 ########################################################################
237 sub _parse_c_warning {
244 $output->write("$line." . ($column + 1) . ": $message\n");
247 ########################################################################
248 # _parse_c_until_one_of
250 sub _parse_c_until_one_of {
253 my $characters = shift;
254 my $refcurrent = shift;
256 my $refcolumn = shift;
259 local $_ = $$refcurrent;
260 my $line = $$refline;
261 my $column = $$refcolumn;
263 if(!defined($match)) {
265 $match = \$blackhole;
269 while(/^[^$characters]/s) {
272 if(s/^[^$characters\n\t\'\"]*//s) {
278 while(/^./ && !s/^\'//) {
294 $$match .= $submatch;
295 $column += length($submatch);
298 while(/^./ && !s/^\"//) {
314 $$match .= $submatch;
315 $column += length($submatch);
319 $$match .= $submatch;
325 $$match .= $submatch;
326 $column = $column + 8 - $column % 8;
328 $$match .= $submatch;
329 $column += length($submatch);
335 $$refcolumn = $column;
339 ########################################################################
342 sub _update_c_position {
347 my $refcolumn = shift;
349 my $line = $$refline;
350 my $column = $$refcolumn;
353 if(s/^[^\n\t\'\"]*//s) {
354 $column += length($&);
359 while(/^./ && !s/^\'//) {
361 $column += length($1);
365 $column += length($1);
368 $column += length($1);
376 while(/^./ && !s/^\"//) {
378 $column += length($1);
382 $column += length($1);
385 $column += length($1);
395 $column = $column + 8 - $column % 8;
400 $$refcolumn = $column;
403 ########################################################################
409 my $refcurrent = shift;
411 my $refcolumn = shift;
413 my $refstatements = shift;
414 my $refstatements_line = shift;
415 my $refstatements_column = shift;
417 local $_ = $$refcurrent;
418 my $line = $$refline;
419 my $column = $$refcolumn;
421 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
431 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
433 my $statements_line = $line;
434 my $statements_column = $column;
439 $self->_parse_c_until_one_of("\\{\\}", \$_, \$line, \$column, \$match);
443 $statements .= $match;
459 $$refcolumn = $column;
460 $$refstatements = $statements;
461 $$refstatements_line = $statements_line;
462 $$refstatements_column = $statements_column;
467 ########################################################################
468 # parse_c_declaration
470 sub parse_c_declaration {
473 my $found_declaration = \${$self->{FOUND_DECLARATION}};
474 my $found_function = \${$self->{FOUND_FUNCTION}};
476 my $refcurrent = shift;
478 my $refcolumn = shift;
480 local $_ = $$refcurrent;
481 my $line = $$refline;
482 my $column = $$refcolumn;
484 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
486 my $begin_line = $line;
487 my $begin_column = $column + 1;
489 my $end_line = $begin_line;
490 my $end_column = $begin_column;
491 $self->_update_c_position($_, \$end_line, \$end_column);
493 if(!&$$found_declaration($begin_line, $begin_column, $end_line, $end_column, $_)) {
498 my $function = shift;
501 my $calling_convention = shift;
502 my $return_type = shift;
504 my @arguments = shift;
505 my @argument_lines = shift;
506 my @argument_columns = shift;
513 } elsif(s/^(?:DEFAULT|DECLARE)_DEBUG_CHANNEL\s*\(\s*(\w+)\s*\)\s*//s) { # FIXME: Wine specific kludge
514 $self->_update_c_position($&, \$line, \$column);
515 } elsif(s/^__ASM_GLOBAL_FUNC\(\s*(\w+)\s*,\s*//s) { # FIXME: Wine specific kludge
516 $self->_update_c_position($&, \$line, \$column);
517 $self->_parse_c_until_one_of("\)", \$_, \$line, \$column);
521 } elsif(s/^(?:jump|strong)_alias//s) { # FIXME: GNU C library specific kludge
522 } elsif(s/^extern\s*\"C\"\s*{//s) {
523 $self->_update_c_position($&, \$line, \$column);
524 } elsif(s/^(?:__asm__|asm)\s*\(//) {
525 $self->_update_c_position($&, \$line, \$column);
526 } elsif($self->parse_c_typedef(\$_, \$line, \$column)) {
528 } elsif($self->parse_c_variable(\$_, \$line, \$column, \$linkage, \$type, \$name)) {
530 } elsif($self->parse_c_function(\$_, \$line, \$column, \$function)) {
531 if(&$$found_function($function))
533 my $statements = $function->statements;
534 my $statements_line = $function->statements_line;
535 my $statements_column = $function->statements_column;
537 if(defined($statements)) {
538 if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
544 $self->_parse_c_error($_, $line, $column, "declaration");
549 $$refcolumn = $column;
554 ########################################################################
555 # parse_c_declarations
557 sub parse_c_declarations {
560 my $refcurrent = shift;
562 my $refcolumn = shift;
567 ########################################################################
570 sub parse_c_expression {
573 my $refcurrent = shift;
575 my $refcolumn = shift;
577 my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
579 local $_ = $$refcurrent;
580 my $line = $$refline;
581 my $column = $$refcolumn;
583 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
586 if(s/^(.*?)(\w+\s*\()/$2/s) {
587 $self->_update_c_position($1, \$line, \$column);
589 my $begin_line = $line;
590 my $begin_column = $column + 1;
595 my @argument_columns;
596 if(!$self->parse_c_function_call(\$_, \$line, \$column, \$name, \@arguments, \@argument_lines, \@argument_columns)) {
600 if(&$$found_function_call($begin_line, $begin_column, $line, $column, $name, \@arguments))
602 while(defined(my $argument = shift @arguments) &&
603 defined(my $argument_line = shift @argument_lines) &&
604 defined(my $argument_column = shift @argument_columns))
606 $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
614 $self->_update_c_position($_, \$line, \$column);
618 $$refcolumn = $column;
623 ########################################################################
629 my $found_comment = \${$self->{FOUND_COMMENT}};
630 my $found_line = \${$self->{FOUND_LINE}};
632 my $refcurrent = shift;
634 my $refcolumn = shift;
636 local $_ = $$refcurrent;
637 my $line = $$refline;
638 my $column = $$refcolumn;
640 my $declaration = "";
641 my $declaration_line = $line;
642 my $declaration_column = $column;
644 my $previous_line = 0;
645 my $previous_column = -1;
652 while($plevel > 0 || $blevel > 0) {
654 $self->_parse_c_until_one_of("#/\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
656 if($line != $previous_line) {
657 &$$found_line($line);
658 } elsif($column == $previous_column) {
659 $self->_parse_c_error($_, $line, $column, "file", "no progress");
661 # &$$found_line("$line.$column");
663 $previous_line = $line;
664 $previous_column = $column;
666 # $output->write("file: $plevel $blevel: '$match'\n");
668 if(!$declaration && $match =~ s/^\s+//s) {
669 $self->_update_c_position($&, \$declaration_line, \$declaration_column);
672 $declaration .= $match;
677 while(s/^.*?\n//) { $blank_lines++; }
680 $declaration_line = $line;
681 $declaration_column = $column;
683 $declaration .= "\n" x $blank_lines;
691 my $preprocessor_line = $line;
692 my $preprocessor_column = $column;
694 my $preprocessor = $&;
695 while(s/^(.*?)\\\s*\n//) {
697 $preprocessor .= "$1\n";
699 if(s/^(.*?)(\/\*.*?\*\/)(.*?)\n//) {
702 $preprocessor .= "$1$3";
706 } elsif(s/^(.*?)(\/[\*\/].*?)?\n//) {
715 if($if0 && $preprocessor =~ /^\#\s*endif/) {
723 } elsif($preprocessor =~ /^\#\s*if/) {
724 if($preprocessor =~ /^\#\s*if\s*0/) {
731 if(!$self->parse_c_preprocessor(\$preprocessor, \$preprocessor_line, \$preprocessor_column)) {
736 if(s/^\/\*.*?\*\///s) {
737 &$$found_comment($line, $column + 1, $&);
743 $column += length($_);
745 } elsif(s/^\/\/(.*?)\n//) {
746 &$$found_comment($line, $column + 1, $&);
755 $line += $blank_lines;
756 if($blank_lines > 0) {
761 $declaration_line = $line;
762 $declaration_column = $column;
763 } elsif($blank_lines > 0) {
764 $declaration .= "\n" x $blank_lines;
786 if($plevel == 1 && $declaration =~ /^__ASM_GLOBAL_FUNC/) {
787 if(!$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
790 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
792 $declaration_line = $line;
793 $declaration_column = $column;
801 if($declaration =~ /^typedef/s ||
802 $declaration =~ /^(?:const\s+|extern\s+|static\s+)*(?:struct|union)(?:\s+\w+)?\s*\{/s)
805 } elsif($plevel == 1 && $blevel == 1) {
806 if(!$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
809 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
811 $declaration_line = $line;
812 $declaration_column = $column;
813 } elsif($column == 1) {
814 $self->_parse_c_error("", $line, $column, "file", "inner } ends on column 1");
819 $declaration !~ /^typedef/ &&
820 $declaration !~ /^(?:const\s+|extern\s+|static\s+)(?:struct|union)(?:\s+\w+)?\s*\{/s &&
821 $declaration =~ /^(?:\w+\s*)*(?:(?:\*\s*)+|\s+)(\w+)\s*\(\s*(?:(?:\w+\s*,\s*)*\w+\s*)?\)(.*?);/s &&
822 $1 ne "ICOM_VTABLE" && $2) # K&R
824 $self->_parse_c_warning($line, $column, "function $1: warning: function has K&R format");
825 } elsif($plevel == 1 && $blevel == 1) {
826 $declaration =~ s/\s*;$//;
827 if($declaration && !$self->parse_c_declaration(\$declaration, \$declaration_line, \$declaration_column)) {
830 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
832 $declaration_line = $line;
833 $declaration_column = $column;
835 } elsif(/^\s*$/ && $declaration =~ /^\s*$/ && $match =~ /^\s*$/) {
839 $self->_parse_c_error($_, $line, $column, "file", "'$declaration' '$match'");
845 $$refcolumn = $column;
850 ########################################################################
853 sub parse_c_function {
856 my $file = \${$self->{FILE}};
857 my $create_function = \${$self->{CREATE_FUNCTION}};
859 my $refcurrent = shift;
861 my $refcolumn = shift;
863 my $reffunction = shift;
865 local $_ = $$refcurrent;
866 my $line = $$refline;
867 my $column = $$refcolumn;
870 my $calling_convention = "";
875 my @argument_columns;
878 my $statements_column;
880 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
882 my $begin_line = $line;
883 my $begin_column = $column + 1;
886 while($self->_parse_c('const|inline|extern|static|volatile|' .
887 'signed(?=\\s+char|s+int|\s+long(?:\s+long)?|\s+short)|' .
888 'unsigned(?=\s+char|\s+int|\s+long(?:\s+long)?|\s+short)',
889 \$_, \$line, \$column, \$match))
891 if($match =~ /^extern|static$/) {
901 } elsif($self->_parse_c('DECL_GLOBAL_CONSTRUCTOR', \$_, \$line, \$column, \$name)) { # FIXME: Wine specific kludge
903 } elsif($self->_parse_c('WINE_EXCEPTION_FILTER\(\w+\)', \$_, \$line, \$column, \$name)) { # FIXME: Wine specific kludge
906 if(!$self->parse_c_type(\$_, \$line, \$column, \$return_type)) {
910 $self->_parse_c("__cdecl|__stdcall|inline|CDECL|VFWAPIV|VFWAPI|WINAPIV|WINAPI|CALLBACK|WINE_UNUSED|PASCAL",
911 \$_, \$line, \$column, \$calling_convention);
913 if(!$self->_parse_c('\w+', \$_, \$line, \$column, \$name)) {
917 if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
923 # FIXME: Implement proper handling of K&R C functions
924 $self->_parse_c_until_one_of("{", \$_, \$line, \$column, $kar);
927 $output->write("K&R: $kar\n");
930 if($_ && !$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
934 my $end_line = $line;
935 my $end_column = $column;
939 $$refcolumn = $column;
941 my $function = &$$create_function;
943 $function->file($$file);
944 $function->begin_line($begin_line);
945 $function->begin_column($begin_column);
946 $function->end_line($end_line);
947 $function->end_column($end_column);
948 $function->linkage($linkage);
949 $function->return_type($return_type);
950 $function->calling_convention($calling_convention);
951 $function->name($name);
952 # if(defined($argument_types)) {
953 # $function->argument_types([@$argument_types]);
955 # if(defined($argument_names)) {
956 # $function->argument_names([@$argument_names]);
958 $function->statements_line($statements_line);
959 $function->statements_column($statements_column);
960 $function->statements($statements);
962 $$reffunction = $function;
967 ########################################################################
968 # parse_c_function_call
970 sub parse_c_function_call {
973 my $refcurrent = shift;
975 my $refcolumn = shift;
978 my $refarguments = shift;
979 my $refargument_lines = shift;
980 my $refargument_columns = shift;
982 local $_ = $$refcurrent;
983 my $line = $$refline;
984 my $column = $$refcolumn;
989 my @argument_columns;
991 if(s/^(\w+)(\s*)(?=\()//s) {
992 $self->_update_c_position($&, \$line, \$column);
996 if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
1005 $$refcolumn = $column;
1008 @$refarguments = @arguments;
1009 @$refargument_lines = @argument_lines;
1010 @$refargument_columns = @argument_columns;
1015 ########################################################################
1016 # parse_c_preprocessor
1018 sub parse_c_preprocessor {
1021 my $found_preprocessor = \${$self->{FOUND_PREPROCESSOR}};
1023 my $refcurrent = shift;
1024 my $refline = shift;
1025 my $refcolumn = shift;
1027 local $_ = $$refcurrent;
1028 my $line = $$refline;
1029 my $column = $$refcolumn;
1031 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1033 my $begin_line = $line;
1034 my $begin_column = $column + 1;
1036 if(!&$$found_preprocessor($begin_line, $begin_column, "$_")) {
1042 } elsif(/^\#\s*define\s*(.*?)$/s) {
1043 $self->_update_c_position($_, \$line, \$column);
1044 } elsif(/^\#\s*else/s) {
1045 $self->_update_c_position($_, \$line, \$column);
1046 } elsif(/^\#\s*endif/s) {
1047 $self->_update_c_position($_, \$line, \$column);
1048 } elsif(/^\#\s*(?:if|ifdef|ifndef)?\s*(.*?)$/s) {
1049 $self->_update_c_position($_, \$line, \$column);
1050 } elsif(/^\#\s*include\s+(.*?)$/s) {
1051 $self->_update_c_position($_, \$line, \$column);
1052 } elsif(/^\#\s*undef\s+(.*?)$/s) {
1053 $self->_update_c_position($_, \$line, \$column);
1055 $self->_parse_c_error($_, $line, $column, "preprocessor");
1060 $$refcolumn = $column;
1065 ########################################################################
1068 sub parse_c_statement {
1071 my $refcurrent = shift;
1072 my $refline = shift;
1073 my $refcolumn = shift;
1075 my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
1077 local $_ = $$refcurrent;
1078 my $line = $$refline;
1079 my $column = $$refcolumn;
1081 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1083 $self->_parse_c('(?:case\s+)?(\w+)\s*:\s*', \$_, \$line, \$column);
1085 # $output->write("$line.$column: statement: '$_'\n");
1091 my $statements_line;
1092 my $statements_column;
1093 if(!$self->parse_c_block(\$_, \$line, \$column, \$statements, \$statements_line, \$statements_column)) {
1096 if(!$self->parse_c_statements(\$statements, \$statements_line, \$statements_column)) {
1099 } elsif(s/^(for|if|switch|while)\s*(?=\()//) {
1100 $self->_update_c_position($&, \$line, \$column);
1106 my @argument_columns;
1107 if(!$self->parse_c_tuple(\$_, \$line, \$column, \@arguments, \@argument_lines, \@argument_columns)) {
1111 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1112 if(!$self->parse_c_statement(\$_, \$line, \$column)) {
1115 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1117 while(defined(my $argument = shift @arguments) &&
1118 defined(my $argument_line = shift @argument_lines) &&
1119 defined(my $argument_column = shift @argument_columns))
1121 $self->parse_c_expression(\$argument, \$argument_line, \$argument_column);
1123 } elsif(s/^else//) {
1124 $self->_update_c_position($&, \$line, \$column);
1125 if(!$self->parse_c_statement(\$_, \$line, \$column)) {
1128 } elsif(s/^return//) {
1129 $self->_update_c_position($&, \$line, \$column);
1130 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1131 if(!$self->parse_c_expression(\$_, \$line, \$column)) {
1134 } elsif($self->parse_c_expression(\$_, \$line, \$column)) {
1137 # $self->_parse_c_error($_, $line, $column, "statement");
1140 $self->_update_c_position($_, \$line, \$column);
1144 $$refcolumn = $column;
1149 ########################################################################
1150 # parse_c_statements
1152 sub parse_c_statements {
1155 my $refcurrent = shift;
1156 my $refline = shift;
1157 my $refcolumn = shift;
1159 my $found_function_call = \${$self->{FOUND_FUNCTION_CALL}};
1161 local $_ = $$refcurrent;
1162 my $line = $$refline;
1163 my $column = $$refcolumn;
1165 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1167 # $output->write("$line.$column: statements: '$_'\n");
1170 my $statement_line = $line;
1171 my $statement_column = $column;
1173 my $previous_line = -1;
1174 my $previous_column = -1;
1178 while($plevel > 0 || $blevel > 0) {
1180 $self->_parse_c_until_one_of("\\(\\)\\[\\]\\{\\};", \$_, \$line, \$column, \$match);
1182 if($previous_line == $line && $previous_column == $column) {
1183 $self->_parse_c_error($_, $line, $column, "statements", "no progress");
1185 $previous_line = $line;
1186 $previous_column = $column;
1188 # $output->write("'$match' '$_'\n");
1190 $statement .= $match;
1195 } elsif(s/^[\)\]]//) {
1198 $self->_parse_c_error($_, $line, $column, "statements");
1208 if(!$self->parse_c_statement(\$statement, \$statement_line, \$statement_column)) {
1211 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1213 $statement_line = $line;
1214 $statement_column = $column;
1217 if($plevel == 1 && $blevel == 1) {
1218 if(!$self->parse_c_statement(\$statement, \$statement_line, \$statement_column)) {
1222 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1224 $statement_line = $line;
1225 $statement_column = $column;
1229 } elsif(/^\s*$/ && $statement =~ /^\s*$/ && $match =~ /^\s*$/) {
1233 $self->_parse_c_error($_, $line, $column, "statements");
1237 $self->_update_c_position($_, \$line, \$column);
1241 $$refcolumn = $column;
1246 ########################################################################
1252 my $refcurrent = shift;
1253 my $refline = shift;
1254 my $refcolumn = shift;
1256 # FIXME: Should not write directly
1258 my $item_lines = shift;
1259 my $item_columns = shift;
1261 local $_ = $$refcurrent;
1263 my $line = $$refline;
1264 my $column = $$refcolumn;
1274 my $item_line = $line;
1275 my $item_column = $column + 1;
1278 while($plevel > 0) {
1280 $self->_parse_c_until_one_of("\\(,\\)", \$_, \$line, \$column, \$match);
1288 push @$item_lines, $item_line;
1289 push @$item_columns, $item_column;
1290 push @$items, $item;
1300 push @$item_lines, $item_line;
1301 push @$item_columns, $item_column;
1302 push @$items, $item;
1303 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1305 $item_column = $column + 1;
1317 $$refcolumn = $column;
1322 ########################################################################
1328 my $refcurrent = shift;
1329 my $refline = shift;
1330 my $refcolumn = shift;
1332 my $reftype = shift;
1334 local $_ = $$refcurrent;
1335 my $line = $$refline;
1336 my $column = $$refcolumn;
1340 $self->_parse_c("const", \$_, \$line, \$column);
1344 } elsif($self->_parse_c('ICOM_VTABLE\(.*?\)', \$_, \$line, \$column, \$type)) {
1346 } elsif($self->_parse_c('(?:enum\s+|struct\s+|union\s+)?\w+\s*(\*\s*)*', \$_, \$line, \$column, \$type)) {
1355 $$refcolumn = $column;
1362 ########################################################################
1365 sub parse_c_typedef {
1368 my $refcurrent = shift;
1369 my $refline = shift;
1370 my $refcolumn = shift;
1372 my $reftype = shift;
1374 local $_ = $$refcurrent;
1375 my $line = $$refline;
1376 my $column = $$refcolumn;
1380 if($self->_parse_c("typedef", \$_, \$line, \$column)) {
1382 } elsif($self->_parse_c('enum(?:\s+\w+)?\s*\{', \$_, \$line, \$column)) {
1390 $$refcolumn = $column;
1397 ########################################################################
1400 sub parse_c_variable {
1403 my $found_variable = \${$self->{FOUND_VARIABLE}};
1405 my $refcurrent = shift;
1406 my $refline = shift;
1407 my $refcolumn = shift;
1409 my $reflinkage = shift;
1410 my $reftype = shift;
1411 my $refname = shift;
1413 local $_ = $$refcurrent;
1414 my $line = $$refline;
1415 my $column = $$refcolumn;
1417 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1419 my $begin_line = $line;
1420 my $begin_column = $column + 1;
1427 while($self->_parse_c('const|inline|extern|static|volatile|' .
1428 'signed(?=\\s+char|s+int|\s+long(?:\s+long)?|\s+short)|' .
1429 'unsigned(?=\s+char|\s+int|\s+long(?:\s+long)?|\s+short)',
1430 \$_, \$line, \$column, \$match))
1432 if($match =~ /^extern|static$/) {
1443 } elsif($self->_parse_c('SEQ_DEFINEBUF', \$_, \$line, \$column, \$match)) { # Linux specific
1446 } elsif($self->_parse_c('DEFINE_GUID', \$_, \$line, \$column, \$match)) { # Windows specific
1449 } elsif($self->_parse_c('DEFINE_REGS_ENTRYPOINT_\w+|DPQ_DECL_\w+|HANDLER_DEF|IX86_ONLY', # Wine specific
1450 \$_, \$line, \$column, \$match))
1454 } elsif($self->_parse_c('(?:struct\s+)?ICOM_VTABLE\s*\(\w+\)', \$_, \$line, \$column, \$match)) {
1457 } elsif(s/^(?:enum\s+|struct\s+|union\s+)(\w+)?\s*\{.*?\}\s*//s) {
1458 $self->_update_c_position($&, \$line, \$column);
1461 $type = "struct $1 { }";
1463 $type = "struct { }";
1472 } elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+)\s*(?:\*\s*)*//s) {
1479 # $output->write("$type: '$_'\n");
1483 } elsif(s/^WINAPI\s*//) {
1484 $self->_update_c_position($&, \$line, \$column);
1489 } elsif(s/^(\((?:__cdecl)?\s*\*?\s*(?:__cdecl)?\w+\s*(?:\[[^\]]*\]\s*)*\))\s*\(//) {
1490 $self->_update_c_position($&, \$line, \$column);
1495 $self->_parse_c_until_one_of("\\)", \$_, \$line, \$column);
1496 if(s/^\)//) { $column++; }
1497 $self->_parse_c_until_one_of("\\S", \$_, \$line, \$column);
1499 if(!s/^(?:=\s*|,\s*|$)//) {
1502 } elsif(s/^(?:\*\s*)*(?:const\s+)?(\w+)\s*(?:\[[^\]]*\]\s*)*\s*(?:=\s*|,\s*|$)//) {
1503 $self->_update_c_position($&, \$line, \$column);
1513 # $output->write("$type: $name: '$_'\n");
1517 } elsif($self->_parse_c('(?:struct\s+)?ICOM_VTABLE\s*\(.*?\)', \$_, \$line, \$column, \$match)) {
1520 } elsif(s/^((?:enum\s+|struct\s+|union\s+)?\w+)\s*
1521 (?:\*\s*)*(\w+|\s*\*?\s*\w+\s*\))\s*(?:\[[^\]]*\]|\([^\)]*\))?
1522 (?:,\s*(?:\*\s*)*(\w+)\s*(?:\[[^\]]*\])?)*
1525 $self->_update_c_position($&, \$line, \$column);
1531 $type =~ s/^struct/struct /;
1532 } elsif(/^(?:enum|struct|union)(?:\s+(\w+))?\s*\{.*?\}\s*((?:\*\s*)*)(\w+)\s*(?:=|$)/s) {
1533 $self->_update_c_position($&, \$line, \$column);
1536 $type = "struct $1 { }";
1538 $type = "struct { }";
1557 $$refcolumn = $column;
1559 $$reflinkage = $linkage;
1563 if(&$$found_variable($begin_line, $begin_column, $linkage, $type, $name))