1################################################### 2# Trivial Parser Generator 3# Copyright jelmer@samba.org 2005-2007 4# released under the GNU GPL 5 6package Parse::Pidl::Samba4::TDR; 7use Parse::Pidl qw(fatal); 8use Parse::Pidl::Util qw(has_property ParseExpr is_constant); 9use Parse::Pidl::Samba4 qw(is_intree choose_header); 10use Parse::Pidl::Typelist qw(mapTypeName); 11 12use Exporter; 13@ISA = qw(Exporter); 14@EXPORT_OK = qw(ParserType $ret $ret_hdr); 15 16use vars qw($VERSION); 17$VERSION = '0.01'; 18 19use strict; 20 21sub new($) { 22 my ($class) = shift; 23 my $self = { ret => "", ret_hdr => "", tabs => "" }; 24 bless($self, $class); 25} 26 27sub indent($) { my $self = shift; $self->{tabs}.="\t"; } 28sub deindent($) { my $self = shift; $self->{tabs} = substr($self->{tabs}, 1); } 29sub pidl($$) { my $self = shift; $self->{ret} .= $self->{tabs}.(shift)."\n"; } 30sub pidl_hdr($$) { my $self = shift; $self->{ret_hdr} .= (shift)."\n"; } 31sub typearg($) { 32 my $t = shift; 33 return(", const char *name") if ($t eq "print"); 34 return(", TALLOC_CTX *mem_ctx") if ($t eq "pull"); 35 return(""); 36} 37 38sub fn_declare($$$) 39{ 40 my ($self, $p, $d) = @_; 41 if ($p) { 42 $self->pidl($d); $self->pidl_hdr("$d;"); 43 } else { 44 $self->pidl("static $d"); 45 } 46} 47 48sub ContainsArray($) 49{ 50 my $e = shift; 51 foreach (@{$e->{ELEMENTS}}) { 52 next if (has_property($_, "charset") and 53 scalar(@{$_->{ARRAY_LEN}}) == 1); 54 return 1 if (defined($_->{ARRAY_LEN}) and 55 scalar(@{$_->{ARRAY_LEN}}) > 0); 56 } 57 return 0; 58} 59 60sub ParserElement($$$$) 61{ 62 my ($self, $e,$t,$env) = @_; 63 my $switch = ""; 64 my $array = ""; 65 my $name = ""; 66 my $mem_ctx = "mem_ctx"; 67 68 fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0); 69 fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is")); 70 fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is")); 71 72 if ($t eq "print") { 73 $name = ", \"$e->{NAME}\"$array"; 74 } 75 76 if (has_property($e, "flag")) { 77 $self->pidl("{"); 78 $self->indent; 79 $self->pidl("uint32_t saved_flags = tdr->flags;"); 80 $self->pidl("tdr->flags |= $e->{PROPERTIES}->{flag};"); 81 } 82 83 if (has_property($e, "charset")) { 84 fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0); 85 86 my $len = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env, $e); 87 if ($len eq "*") { $len = "-1"; } 88 $name = ", mem_ctx" if ($t eq "pull"); 89 $self->pidl("TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));"); 90 return; 91 } 92 93 if (has_property($e, "switch_is")) { 94 $switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env, $e); 95 } 96 97 if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) { 98 my $len = ParseExpr($e->{ARRAY_LEN}[0], $env, $e); 99 100 if ($t eq "pull" and not is_constant($len)) { 101 $self->pidl("TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);"); 102 $mem_ctx = "v->$e->{NAME}"; 103 } 104 105 $self->pidl("for (i = 0; i < $len; i++) {"); 106 $self->indent; 107 $array = "[i]"; 108 } 109 110 if ($t eq "pull") { 111 $name = ", $mem_ctx"; 112 } 113 114 if (has_property($e, "value") && $t eq "push") { 115 $self->pidl("v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";"); 116 } 117 118 $self->pidl("TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));"); 119 120 if ($array) { $self->deindent; $self->pidl("}"); } 121 122 if (has_property($e, "flag")) { 123 $self->pidl("tdr->flags = saved_flags;"); 124 $self->deindent; 125 $self->pidl("}"); 126 } 127} 128 129sub ParserStruct($$$$$) 130{ 131 my ($self, $e,$t,$p) = @_; 132 133 $self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)"); 134 $self->pidl("{"); $self->indent; 135 $self->pidl("int i;") if (ContainsArray($e)); 136 137 if ($t eq "print") { 138 $self->pidl("tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);"); 139 $self->pidl("tdr->level++;"); 140 } 141 142 my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}}; 143 $env{"this"} = "v"; 144 $self->ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}}); 145 146 if ($t eq "print") { 147 $self->pidl("tdr->level--;"); 148 } 149 150 $self->pidl("return NT_STATUS_OK;"); 151 152 $self->deindent; $self->pidl("}"); 153} 154 155sub ParserUnion($$$$) 156{ 157 my ($self, $e,$t,$p) = @_; 158 159 $self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)"); 160 $self->pidl("{"); $self->indent; 161 $self->pidl("int i;") if (ContainsArray($e)); 162 163 if ($t eq "print") { 164 $self->pidl("tdr->print(tdr, \"\%-25s: union $e->{NAME}\", name);"); 165 $self->pidl("tdr->level++;"); 166 } 167 168 $self->pidl("switch (level) {"); $self->indent; 169 foreach (@{$e->{ELEMENTS}}) { 170 if (has_property($_, "case")) { 171 $self->pidl("case " . $_->{PROPERTIES}->{case} . ":"); 172 } elsif (has_property($_, "default")) { 173 $self->pidl("default:"); 174 } 175 $self->indent; $self->ParserElement($_, $t, {}); $self->deindent; 176 $self->pidl("break;"); 177 } 178 $self->deindent; $self->pidl("}"); 179 180 if ($t eq "print") { 181 $self->pidl("tdr->level--;"); 182 } 183 184 $self->pidl("return NT_STATUS_OK;\n"); 185 $self->deindent; $self->pidl("}"); 186} 187 188sub ParserBitmap($$$$) 189{ 190 my ($self,$e,$t,$p) = @_; 191 return if ($p); 192 $self->pidl("#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e)); 193} 194 195sub ParserEnum($$$$) 196{ 197 my ($self,$e,$t,$p) = @_; 198 my $bt = Parse::Pidl::Typelist::enum_type_fn($e); 199 my $mt = mapTypeName($bt); 200 201 $self->fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)"); 202 $self->pidl("{"); 203 if ($t eq "pull") { 204 $self->pidl("\t$mt r;"); 205 $self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));"); 206 $self->pidl("\t*v = r;"); 207 } elsif ($t eq "push") { 208 $self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, ($mt *)v));"); 209 } elsif ($t eq "print") { 210 $self->pidl("\t/* FIXME */"); 211 } 212 $self->pidl("\treturn NT_STATUS_OK;"); 213 $self->pidl("}"); 214} 215 216sub ParserTypedef($$$$) 217{ 218 my ($self, $e,$t,$p) = @_; 219 220 $self->ParserType($e->{DATA},$t); 221} 222 223sub ParserType($$$) 224{ 225 my ($self, $e,$t) = @_; 226 227 return if (has_property($e, "no$t")); 228 229 my $handlers = { 230 STRUCT => \&ParserStruct, UNION => \&ParserUnion, 231 ENUM => \&ParserEnum, BITMAP => \&ParserBitmap, 232 TYPEDEF => \&ParserTypedef 233 }; 234 235 $handlers->{$e->{TYPE}}->($self, $e, $t, has_property($e, "public")) 236 if (defined($handlers->{$e->{TYPE}})); 237 238 $self->pidl(""); 239} 240 241sub ParserInterface($$) 242{ 243 my ($self,$x) = @_; 244 245 $self->pidl_hdr("#ifndef __TDR_$x->{NAME}_HEADER__"); 246 $self->pidl_hdr("#define __TDR_$x->{NAME}_HEADER__"); 247 248 foreach (@{$x->{DATA}}) { 249 $self->ParserType($_, "pull"); 250 $self->ParserType($_, "push"); 251 $self->ParserType($_, "print"); 252 } 253 254 $self->pidl_hdr("#endif /* __TDR_$x->{NAME}_HEADER__ */"); 255} 256 257sub Parser($$$$) 258{ 259 my ($self,$idl,$hdrname,$baseheader) = @_; 260 $self->pidl("/* autogenerated by pidl */"); 261 if (is_intree()) { 262 $self->pidl("#include \"includes.h\""); 263 } else { 264 $self->pidl("#include <stdio.h>"); 265 $self->pidl("#include <stdbool.h>"); 266 $self->pidl("#include <stdlib.h>"); 267 $self->pidl("#include <stdint.h>"); 268 $self->pidl("#include <stdarg.h>"); 269 $self->pidl("#include <string.h>"); 270 $self->pidl("#include <core/ntstatus.h>"); 271 } 272 $self->pidl("#include \"$hdrname\""); 273 $self->pidl(""); 274 $self->pidl_hdr("/* autogenerated by pidl */"); 275 $self->pidl_hdr("#include \"$baseheader\""); 276 $self->pidl_hdr(choose_header("lib/tdr/tdr.h", "tdr.h")); 277 $self->pidl_hdr(""); 278 279 foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); } 280 return ($self->{ret_hdr}, $self->{ret}); 281} 282 2831; 284