2003-12-07 16:38:07 +03:00
########################
# IDL Parse::Yapp parser
# Copyright (C) Andrew Tridgell <tridge@samba.org>
2008-03-28 09:08:49 +03:00
# released under the GNU GPL version 3 or later
2003-12-07 16:38:07 +03:00
2005-08-01 05:39:24 +04:00
# the precedence actually doesn't matter at all for this grammar, but
2003-12-08 05:24:40 +03:00
# by providing a precedence we reduce the number of conflicts
# enormously
%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
2003-12-07 16:38:07 +03:00
################
2005-08-01 05:39:24 +04:00
# grammar
2003-12-07 16:38:07 +03:00
%%
2004-08-11 23:48:36 +04:00
idl:
#empty { {} }
2009-08-04 16:59:33 +04:00
|
idl interface { push(@{$_[1]}, $_[2]); $_[1] }
|
idl coclass { push(@{$_[1]}, $_[2]); $_[1] }
|
idl import { push(@{$_[1]}, $_[2]); $_[1] }
|
idl include { push(@{$_[1]}, $_[2]); $_[1] }
|
idl importlib { push(@{$_[1]}, $_[2]); $_[1] }
|
idl cpp_quote { push(@{$_[1]}, $_[2]); $_[1] }
;
import:
'import' commalist ';'
{{
"TYPE" => "IMPORT",
"PATHS" => $_[2],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
include:
'include' commalist ';'
{{
"TYPE" => "INCLUDE",
"PATHS" => $_[2],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
importlib:
'importlib' commalist ';'
{{
"TYPE" => "IMPORTLIB",
"PATHS" => $_[2],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
commalist:
text { [ $_[1] ] }
|
commalist ',' text { push(@{$_[1]}, $_[3]); $_[1] }
;
coclass:
property_list 'coclass' identifier '{' interface_names '}' optional_semicolon
{{
"TYPE" => "COCLASS",
"PROPERTIES" => $_[1],
"NAME" => $_[3],
"DATA" => $_[5],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
2004-11-01 23:00:02 +03:00
;
2005-02-21 15:13:42 +03:00
interface_names:
2004-11-01 23:00:02 +03:00
#empty { {} }
2009-08-04 16:59:33 +04:00
|
interface_names 'interface' identifier ';' { push(@{$_[1]}, $_[2]); $_[1] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
interface:
property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
{{
"TYPE" => "INTERFACE",
"PROPERTIES" => $_[1],
"NAME" => $_[3],
"BASE" => $_[4],
"DATA" => $_[6],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
2003-12-07 16:38:07 +03:00
;
2008-05-07 19:18:18 +04:00
base_interface:
2009-08-04 16:59:33 +04:00
#empty
|
':' identifier { $_[2] }
2008-05-07 19:18:18 +04:00
;
2009-08-04 16:59:33 +04:00
cpp_quote:
'cpp_quote' '(' text ')'
2007-08-31 04:03:54 +04:00
{{
"TYPE" => "CPP_QUOTE",
2009-08-04 16:59:33 +04:00
"DATA" => $_[3],
2007-08-31 04:03:54 +04:00
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
2009-08-04 16:59:33 +04:00
definitions:
definition { [ $_[1] ] }
|
definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
definition:
function
|
const
|
typedef
|
typedecl
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
const:
'const' identifier pointers identifier '=' anytext ';'
{{
"TYPE" => "CONST",
"DTYPE" => $_[2],
"POINTERS" => $_[3],
"NAME" => $_[4],
"VALUE" => $_[6],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
|
'const' identifier pointers identifier array_len '=' anytext ';'
{{
"TYPE" => "CONST",
"DTYPE" => $_[2],
"POINTERS" => $_[3],
"NAME" => $_[4],
"ARRAY_LEN" => $_[5],
"VALUE" => $_[7],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
2003-12-07 16:38:07 +03:00
2009-08-04 16:59:33 +04:00
function:
property_list type identifier '(' element_list2 ')' ';'
{{
2003-12-07 16:38:07 +03:00
"TYPE" => "FUNCTION",
"NAME" => $_[3],
"RETURN_TYPE" => $_[2],
"PROPERTIES" => $_[1],
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
"ELEMENTS" => $_[5],
2007-01-05 18:20:23 +03:00
"FILE" => $_[0]->YYData->{FILE},
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
"LINE" => $_[0]->YYData->{LINE},
2009-08-04 16:59:33 +04:00
}}
;
typedef:
property_list 'typedef' type identifier array_len ';'
{{
"TYPE" => "TYPEDEF",
"PROPERTIES" => $_[1],
"NAME" => $_[4],
"DATA" => $_[3],
"ARRAY_LEN" => $_[5],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
2003-12-07 16:38:07 +03:00
}}
;
2009-08-04 16:59:33 +04:00
usertype:
struct
|
union
|
enum
|
bitmap
2009-08-05 15:40:38 +04:00
|
pipe
2009-08-04 16:59:33 +04:00
;
2005-07-20 03:34:02 +04:00
2009-08-04 16:59:33 +04:00
typedecl:
usertype ';' { $_[1] }
;
2005-07-20 03:34:02 +04:00
2009-08-04 16:59:33 +04:00
sign:
'signed'
|
'unsigned'
;
2005-12-25 17:59:21 +03:00
2009-08-04 16:59:33 +04:00
existingtype:
2007-01-09 09:02:41 +03:00
sign identifier { ($_[1]?$_[1]:"signed") ." $_[2]" }
2009-08-04 16:59:33 +04:00
|
identifier
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
type:
usertype
|
existingtype
|
void { "void" }
;
2005-12-25 17:59:21 +03:00
2009-08-04 16:59:33 +04:00
enum_body:
'{' enum_elements '}' { $_[2] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
opt_enum_body:
#empty
|
enum_body
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
enum:
property_list 'enum' optional_identifier opt_enum_body
{{
"TYPE" => "ENUM",
"PROPERTIES" => $_[1],
"NAME" => $_[3],
"ELEMENTS" => $_[4],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
enum_elements:
enum_element { [ $_[1] ] }
|
enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
2005-01-05 18:26:48 +03:00
;
2009-08-04 16:59:33 +04:00
enum_element:
identifier
|
identifier '=' anytext { "$_[1]$_[2]$_[3]" }
2005-01-05 18:26:48 +03:00
;
2009-08-04 16:59:33 +04:00
bitmap_body:
'{' opt_bitmap_elements '}' { $_[2] }
;
2006-09-07 02:25:54 +04:00
2009-08-04 16:59:33 +04:00
opt_bitmap_body:
#empty
|
bitmap_body
2005-01-05 18:26:48 +03:00
;
2009-08-04 16:59:33 +04:00
bitmap:
property_list 'bitmap' optional_identifier opt_bitmap_body
{{
"TYPE" => "BITMAP",
"PROPERTIES" => $_[1],
"NAME" => $_[3],
"ELEMENTS" => $_[4],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
2005-12-25 17:59:21 +03:00
2009-08-04 16:59:33 +04:00
bitmap_elements:
bitmap_element { [ $_[1] ] }
|
bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
;
opt_bitmap_elements:
#empty
|
bitmap_elements
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
bitmap_element:
identifier '=' anytext { "$_[1] ( $_[3] )" }
;
struct_body:
'{' element_list1 '}' { $_[2] }
;
opt_struct_body:
#empty
|
struct_body
;
struct:
property_list 'struct' optional_identifier opt_struct_body
2005-02-11 05:05:47 +03:00
{{
2009-08-04 16:59:33 +04:00
"TYPE" => "STRUCT",
"PROPERTIES" => $_[1],
"NAME" => $_[3],
"ELEMENTS" => $_[4],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
empty_element:
property_list ';'
{{
"NAME" => "",
"TYPE" => "EMPTY",
"PROPERTIES" => $_[1],
"POINTERS" => 0,
"ARRAY_LEN" => [],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
base_or_empty:
base_element ';'
|
empty_element;
2005-02-11 05:05:47 +03:00
optional_base_element:
2005-12-25 17:59:21 +03:00
property_list base_or_empty { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
2005-02-11 05:05:47 +03:00
;
2009-08-04 16:59:33 +04:00
union_elements:
#empty
|
union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
union_body:
'{' union_elements '}' { $_[2] }
;
2005-12-25 17:59:21 +03:00
2009-08-04 16:59:33 +04:00
opt_union_body:
#empty
|
union_body
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
union:
property_list 'union' optional_identifier opt_union_body
{{
"TYPE" => "UNION",
"PROPERTIES" => $_[1],
"NAME" => $_[3],
"ELEMENTS" => $_[4],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
base_element:
property_list type pointers identifier array_len
{{
"NAME" => $_[4],
"TYPE" => $_[2],
"PROPERTIES" => $_[1],
"POINTERS" => $_[3],
"ARRAY_LEN" => $_[5],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
2003-12-07 16:38:07 +03:00
2009-08-04 16:59:33 +04:00
pointers:
#empty
{ 0 }
|
pointers '*' { $_[1]+1 }
2003-12-07 16:38:07 +03:00
;
2009-08-05 15:40:38 +04:00
pipe:
property_list 'pipe' type
{{
"TYPE" => "PIPE",
"PROPERTIES" => $_[1],
"DATA" => $_[3],
"FILE" => $_[0]->YYData->{FILE},
"LINE" => $_[0]->YYData->{LINE},
}}
;
2009-08-04 16:59:33 +04:00
element_list1:
#empty
2007-03-04 17:16:52 +03:00
{ [] }
2009-08-04 16:59:33 +04:00
|
element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
optional_const:
2008-09-16 06:15:39 +04:00
#empty
2009-08-04 16:59:33 +04:00
|
'const'
2008-09-16 06:15:39 +04:00
;
2009-08-04 16:59:33 +04:00
element_list2:
#empty
|
'void'
|
optional_const base_element { [ $_[2] ] }
|
element_list2 ',' optional_const base_element { push(@{$_[1]}, $_[4]); $_[1] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
array_len:
#empty { [] }
|
'[' ']' array_len { push(@{$_[3]}, "*"); $_[3] }
|
'[' anytext ']' array_len { push(@{$_[4]}, "$_[2]"); $_[4] }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
property_list:
#empty
|
property_list '[' properties ']' { FlattenHash([$_[1],$_[3]]); }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
properties:
property { $_[1] }
|
properties ',' property { FlattenHash([$_[1], $_[3]]); }
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
property:
identifier {{ "$_[1]" => "1" }}
|
identifier '(' commalisttext ')' {{ "$_[1]" => "$_[3]" }}
2003-12-07 16:38:07 +03:00
;
2004-10-14 14:30:08 +04:00
commalisttext:
2009-08-04 16:59:33 +04:00
anytext
|
commalisttext ',' anytext { "$_[1],$_[3]" }
;
anytext:
#empty
{ "" }
|
identifier
|
constant
|
text
|
anytext '-' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '.' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '*' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '>' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '<' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '|' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '&' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '/' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '?' anytext { "$_[1]$_[2]$_[3]" }
|
anytext ':' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '=' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '+' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '~' anytext { "$_[1]$_[2]$_[3]" }
|
anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
|
anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
;
identifier:
2005-07-20 03:34:02 +04:00
IDENTIFIER
;
2009-08-04 16:59:33 +04:00
optional_identifier:
#empty { undef }
|
IDENTIFIER
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
constant:
CONSTANT
2003-12-07 16:38:07 +03:00
;
2009-08-04 16:59:33 +04:00
text:
TEXT { "\"$_[1]\"" }
;
optional_semicolon:
2004-11-01 15:26:59 +03:00
#empty
2009-08-04 16:59:33 +04:00
|
';'
2004-11-01 15:26:59 +03:00
;
2003-12-07 16:38:07 +03:00
#####################################
# start code
%%
2007-01-05 18:20:23 +03:00
use Parse::Pidl qw(error);
2005-12-25 17:59:21 +03:00
#####################################################################
# flatten an array of hashes into a single hash
2009-08-04 16:59:33 +04:00
sub FlattenHash($)
{
my $a = shift;
my %b;
for my $d (@{$a}) {
for my $k (keys %{$d}) {
$b{$k} = $d->{$k};
}
2005-12-25 17:59:21 +03:00
}
2009-08-04 16:59:33 +04:00
return \%b;
2005-12-25 17:59:21 +03:00
}
2005-07-10 05:16:02 +04:00
#####################################################################
# traverse a perl data structure removing any empty arrays or
# hashes and any hash elements that map to undef
sub CleanData($)
{
2009-08-04 16:59:33 +04:00
sub CleanData($);
my($v) = shift;
2005-12-25 02:32:50 +03:00
return undef if (not defined($v));
2009-08-04 16:59:33 +04:00
if (ref($v) eq "ARRAY") {
foreach my $i (0 .. $#{$v}) {
CleanData($v->[$i]);
}
# this removes any undefined elements from the array
@{$v} = grep { defined $_ } @{$v};
} elsif (ref($v) eq "HASH") {
foreach my $x (keys %{$v}) {
CleanData($v->{$x});
if (!defined $v->{$x}) {
delete($v->{$x});
next;
}
}
2005-07-10 05:16:02 +04:00
}
2009-08-04 16:59:33 +04:00
2005-07-10 05:16:02 +04:00
return $v;
}
2003-12-07 16:38:07 +03:00
sub _Error {
2009-08-04 16:59:33 +04:00
if (exists $_[0]->YYData->{ERRMSG}) {
2007-01-05 18:20:23 +03:00
error($_[0]->YYData, $_[0]->YYData->{ERRMSG});
2003-12-07 16:38:07 +03:00
delete $_[0]->YYData->{ERRMSG};
return;
2008-02-26 17:38:45 +03:00
}
2009-08-04 16:59:33 +04:00
2003-12-07 16:38:07 +03:00
my $last_token = $_[0]->YYData->{LAST_TOKEN};
2009-08-04 16:59:33 +04:00
2007-01-05 18:20:23 +03:00
error($_[0]->YYData, "Syntax error near '$last_token'");
2003-12-07 16:38:07 +03:00
}
2003-12-07 16:51:23 +03:00
sub _Lexer($)
{
2003-12-07 16:38:07 +03:00
my($parser)=shift;
2009-08-04 16:59:33 +04:00
$parser->YYData->{INPUT} or return('',undef);
2003-12-07 16:38:07 +03:00
again:
$parser->YYData->{INPUT} =~ s/^[ \t]*//;
for ($parser->YYData->{INPUT}) {
2003-12-07 16:51:23 +03:00
if (/^\#/) {
if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
$parser->YYData->{LINE} = $1-1;
2007-01-05 18:20:23 +03:00
$parser->YYData->{FILE} = $2;
2003-12-07 16:51:23 +03:00
goto again;
}
2003-12-16 03:38:33 +03:00
if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
$parser->YYData->{LINE} = $1-1;
2007-01-05 18:20:23 +03:00
$parser->YYData->{FILE} = $2;
2003-12-16 03:38:33 +03:00
goto again;
}
if (s/^(\#.*)$//m) {
goto again;
}
2003-12-07 16:38:07 +03:00
}
if (s/^(\n)//) {
$parser->YYData->{LINE}++;
goto again;
}
if (s/^\"(.*?)\"//) {
$parser->YYData->{LAST_TOKEN} = $1;
2009-08-04 16:59:33 +04:00
return('TEXT',$1);
2003-12-07 16:38:07 +03:00
}
if (s/^(\d+)(\W|$)/$2/) {
$parser->YYData->{LAST_TOKEN} = $1;
2009-08-04 16:59:33 +04:00
return('CONSTANT',$1);
2003-12-07 16:38:07 +03:00
}
if (s/^([\w_]+)//) {
$parser->YYData->{LAST_TOKEN} = $1;
2009-08-04 16:59:33 +04:00
if ($1 =~
/^(coclass|interface|import|importlib
|include|cpp_quote|typedef
2009-08-05 15:40:38 +04:00
|union|struct|enum|bitmap|pipe
2009-08-04 16:59:33 +04:00
|void|const|unsigned|signed)$/x) {
2003-12-07 16:38:07 +03:00
return $1;
}
return('IDENTIFIER',$1);
}
if (s/^(.)//s) {
$parser->YYData->{LAST_TOKEN} = $1;
return($1,$1);
}
}
}
2005-12-25 02:32:50 +03:00
sub parse_string
2003-12-07 16:38:07 +03:00
{
2005-12-25 02:32:50 +03:00
my ($data,$filename) = @_;
2005-12-25 00:57:51 +03:00
my $self = new Parse::Pidl::IDL;
2009-08-04 16:59:33 +04:00
$self->YYData->{FILE} = $filename;
$self->YYData->{INPUT} = $data;
$self->YYData->{LINE} = 0;
$self->YYData->{LAST_TOKEN} = "NONE";
2005-12-25 00:57:51 +03:00
my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
return CleanData($idl);
}
2006-11-06 23:01:22 +03:00
sub parse_file($$)
2005-12-25 00:57:51 +03:00
{
2006-11-06 23:01:22 +03:00
my ($filename,$incdirs) = @_;
2003-12-07 16:38:07 +03:00
my $saved_delim = $/;
undef $/;
2003-12-16 01:06:18 +03:00
my $cpp = $ENV{CPP};
if (! defined $cpp) {
2005-09-09 01:59:40 +04:00
$cpp = "cpp";
2003-12-16 01:06:18 +03:00
}
2006-11-07 04:00:27 +03:00
my $includes = join('',map { " -I$_" } @$incdirs);
2009-02-10 01:29:41 +03:00
my $data = `$cpp -D__PIDL__$includes -xc $filename`;
2003-12-07 16:38:07 +03:00
$/ = $saved_delim;
2005-12-25 02:32:50 +03:00
return parse_string($data, $filename);
2003-12-07 16:38:07 +03:00
}