summaryrefslogtreecommitdiff
path: root/source4/pidl/smb_interfaces.yp
diff options
context:
space:
mode:
Diffstat (limited to 'source4/pidl/smb_interfaces.yp')
-rw-r--r--source4/pidl/smb_interfaces.yp233
1 files changed, 233 insertions, 0 deletions
diff --git a/source4/pidl/smb_interfaces.yp b/source4/pidl/smb_interfaces.yp
new file mode 100644
index 0000000000..f8c34eacdc
--- /dev/null
+++ b/source4/pidl/smb_interfaces.yp
@@ -0,0 +1,233 @@
+########################
+# Parse::Yapp parser for a C header file that contains only structures
+# or unions.
+
+# Copyright (C) 2005, Tim Potter <tpot@samba.org> released under the
+# GNU GPL version 2 or later
+
+################
+# grammar
+
+%%
+
+definitions:
+ definition { [$_[1]] }
+ | definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
+;
+
+definition:
+ struct
+ | union
+ | typedef
+ | enum
+;
+
+struct: STRUCT optional_identifier '{' elements '}' pointers optional_identifiers ';'
+ {
+ {
+ "NAME" => $_[7],
+ "STRUCT_NAME" => $_[2],
+ "TYPE" => "struct",
+ "DATA" => $_[4],
+ }
+ }
+;
+
+union:
+ UNION optional_identifier '{' elements '}' pointers optional_identifier ';'
+ {
+ {
+ "NAME" => $_[7],
+ "UNION_NAME" => $_[2],
+ "TYPE" => "union",
+ "DATA" => $_[4],
+ }
+ }
+;
+
+typedef:
+ TYPEDEF STRUCT '{' elements '}' optional_identifier ';'
+;
+
+enum:
+ ENUM IDENTIFIER '{' enum_identifiers '}' ';'
+;
+
+enum_identifiers: enum_identifier
+ | enum_identifiers ',' enum_identifier
+;
+
+enum_identifier: IDENTIFIER
+ | IDENTIFIER '=' IDENTIFIER
+;
+
+elements: #empty
+ | elements element { push(@{$_[1]}, $_[2]); $_[1] }
+;
+
+element:
+ | struct
+ | union
+ | STRUCT IDENTIFIER pointers IDENTIFIER ';'
+ {{
+ "NAME" => [$_[2]],
+ "POINTERS" => $_[3],
+ "TYPE" => "struct $_[2]",
+ }}
+ | UNION IDENTIFIER pointers IDENTIFIER ';'
+ {{
+ "NAME" => $_[2],
+ "POINTERS" => $_[3],
+ "TYPE" => "union $_[2]",
+ }}
+ | CONST type pointers IDENTIFIER array ';'
+ {{
+ "NAME" => [$_[4]],
+ "TYPE" => $_[2],
+ "POINTERS" => $_[3],
+ }}
+ | type pointers IDENTIFIER array ';'
+ {{
+ "NAME" => [$_[3]],
+ "TYPE" => $_[1],
+ "POINTERS" => $_[2],
+ "ARRAY_LENGTH" => $_[4]
+ }}
+;
+
+array: #empty
+ | '[' CONSTANT ']' { int($_[2]) }
+;
+
+type: IDENTIFIER
+ | ENUM IDENTIFIER
+ { "enum $_[2]" }
+;
+
+pointers:
+ #empty { 0 }
+ | pointers '*' { $_[1]+1 }
+;
+
+optional_identifiers: optional_identifier { [$_[1]] }
+ | optional_identifiers ',' optional_identifier { push(@{$_[1]}, $_[3]); $_[1] }
+;
+
+optional_identifier: IDENTIFIER | #empty { undef }
+;
+
+%%
+
+#####################################################################
+# traverse a perl data structure removing any empty arrays or
+# hashes and any hash elements that map to undef
+sub CleanData($)
+{
+ sub CleanData($);
+ my($v) = shift;
+ if (ref($v) eq "ARRAY") {
+ foreach my $i (0 .. $#{$v}) {
+ CleanData($v->[$i]);
+ if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) {
+ $v->[$i] = undef;
+ next;
+ }
+ }
+ # 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; }
+ if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; }
+ }
+ }
+ return $v;
+}
+
+sub _Error {
+ if (exists $_[0]->YYData->{ERRMSG}) {
+ print $_[0]->YYData->{ERRMSG};
+ delete $_[0]->YYData->{ERRMSG};
+ return;
+ };
+ my $line = $_[0]->YYData->{LINE};
+ my $last_token = $_[0]->YYData->{LAST_TOKEN};
+ my $file = $_[0]->YYData->{INPUT_FILENAME};
+
+ print "$file:$line: Syntax error near '$last_token'\n";
+}
+
+sub _Lexer($)
+{
+ my($parser)=shift;
+
+ $parser->YYData->{INPUT} or return('',undef);
+
+again:
+ $parser->YYData->{INPUT} =~ s/^[ \t]*//;
+
+ for ($parser->YYData->{INPUT}) {
+ if (/^\#/) {
+ if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
+ $parser->YYData->{LINE} = $1-1;
+ $parser->YYData->{INPUT_FILENAME} = $2;
+ goto again;
+ }
+ if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
+ $parser->YYData->{LINE} = $1-1;
+ $parser->YYData->{INPUT_FILENAME} = $2;
+ goto again;
+ }
+ if (s/^(\#.*)$//m) {
+ goto again;
+ }
+ }
+ if (s/^(\n)//) {
+ $parser->YYData->{LINE}++;
+ goto again;
+ }
+ if (s/^\"(.*?)\"//) {
+ $parser->YYData->{LAST_TOKEN} = $1;
+ return('TEXT',$1);
+ }
+ if (s/^(\d+)(\W|$)/$2/) {
+ $parser->YYData->{LAST_TOKEN} = $1;
+ return('CONSTANT',$1);
+ }
+ if (s/^([\w_]+)//) {
+ $parser->YYData->{LAST_TOKEN} = $1;
+ if ($1 =~
+ /^(const|typedef|union|struct|enum)$/x) {
+ return uc($1);
+ }
+ return('IDENTIFIER',$1);
+ }
+ if (s/^(.)//s) {
+ $parser->YYData->{LAST_TOKEN} = $1;
+ return($1,$1);
+ }
+ }
+}
+
+sub parse($$)
+{
+ my ($self,$filename) = @_;
+
+ my $saved_delim = $/;
+ undef $/;
+ my $cpp = $ENV{CPP};
+ if (! defined $cpp) {
+ $cpp = "cpp"
+ }
+ my $data = `$cpp -D__PIDL__ -xc $filename`;
+ $/ = $saved_delim;
+
+ $self->YYData->{INPUT} = $data;
+ $self->YYData->{LINE} = 0;
+ $self->YYData->{LAST_TOKEN} = "NONE";
+
+ my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
+
+ return CleanData($idl);
+}