1 ###################################################
2 # create C header files for an IDL structure
3 # Copyright tridge@samba.org 2000
4 # Copyright jelmer@samba.org 2005
5 # released under the GNU GPL
7 package Parse::Pidl::Samba::NDR::Header;
10 use Parse::Pidl::Typelist;
11 use Parse::Pidl::Samba::NDR::Parser;
23 for (my($i)=0; $i < $tab_depth; $i++) {
28 #####################################################################
29 # parse a properties list
30 sub HeaderProperties($$)
32 my($props,$ignores) = @_;
35 foreach my $d (keys %{$props}) {
36 next if (grep(/^$d$/, @$ignores));
37 if($props->{$d} ne "1") {
38 $ret.= "$d($props->{$d}),";
45 pidl "/* [" . substr($ret, 0, -1) . "] */";
49 #####################################################################
50 # parse a structure element
56 HeaderType($element, $element->{TYPE}, "");
60 foreach my $l (@{$element->{LEVELS}})
62 if (($l->{TYPE} eq "POINTER")) {
63 my $nl = Parse::Pidl::NDR::GetNextLevel($element, $l);
64 $nl = Parse::Pidl::NDR::GetNextLevel($element, $nl) if ($nl->{TYPE} eq "SUBCONTEXT");
65 next if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE}));
67 } elsif ($l->{TYPE} eq "ARRAY") {
68 my $pl = Parse::Pidl::NDR::GetPrevLevel($element, $l);
69 next if ($pl and $pl->{TYPE} eq "POINTER");
72 $postfix .= "[$l->{SIZE_IS}]";
76 } elsif ($l->{TYPE} eq "DATA") {
77 pidl "$prefix$element->{NAME}$postfix";
81 if (defined $element->{ARRAY_LEN}[0] && Parse::Pidl::Util::is_constant($element->{ARRAY_LEN}[0])) {
82 pidl "[$element->{ARRAY_LEN}[0]]";
85 if (defined $element->{PROPERTIES}) {
86 HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
91 #####################################################################
95 my($struct,$name) = @_;
96 pidl "\nstruct $name {\n";
99 if (defined $struct->{ELEMENTS}) {
100 foreach my $e (@{$struct->{ELEMENTS}}) {
105 if ($el_count == 0) {
106 # some compilers can't handle empty structures
107 pidl "\tchar _empty_;\n";
111 if (defined $struct->{PROPERTIES}) {
112 HeaderProperties($struct->{PROPERTIES}, []);
116 #####################################################################
120 my($enum,$name) = @_;
123 if (not Parse::Pidl::Util::useUintEnums()) {
124 pidl "\nenum $name {\n";
126 foreach my $e (@{$enum->{ELEMENTS}}) {
127 unless ($first) { pidl ",\n"; }
137 pidl "\nenum $name { __donnot_use_enum_$name=0x7FFFFFFF};\n";
140 foreach my $e (@{$enum->{ELEMENTS}}) {
144 if ($t =~ /(.*)=(.*)/) {
148 die ("you can't mix enum member with values and without values when using --uint-enums!")
149 unless ($without_val == 0);
154 die ("you can't mix enum member with values and without values when using --uint-enums!")
155 unless ($with_val == 0);
157 pidl "#define $name ( $value )\n";
163 #####################################################################
167 my($bitmap,$name) = @_;
169 pidl "\n/* bitmap $name */\n";
171 foreach my $e (@{$bitmap->{ELEMENTS}})
179 #####################################################################
183 my($union,$name) = @_;
186 pidl "\nunion $name {\n";
188 foreach my $e (@{$union->{ELEMENTS}}) {
189 if ($e->{TYPE} ne "EMPTY") {
190 if (! defined $done{$e->{NAME}}) {
193 $done{$e->{NAME}} = 1;
199 if (defined $union->{PROPERTIES}) {
200 HeaderProperties($union->{PROPERTIES}, []);
204 #####################################################################
208 my($e,$data,$name) = @_;
209 if (ref($data) eq "HASH") {
210 ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name);
211 ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
212 ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name);
213 ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name);
217 if (Parse::Pidl::Util::has_property($e, "charset")) {
220 pidl Parse::Pidl::Typelist::mapType($e->{TYPE});
224 #####################################################################
228 my($typedef) = shift;
229 HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
230 pidl ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
233 #####################################################################
234 # prototype a typedef
235 sub HeaderTypedefProto($)
239 my $tf = Parse::Pidl::Samba::NDR::Parser::get_typefamily($d->{DATA}{TYPE});
241 if (Parse::Pidl::Util::has_property($d, "gensize")) {
242 my $size_args = $tf->{SIZE_FN_ARGS}->($d);
243 pidl "size_t ndr_size_$d->{NAME}($size_args);\n";
246 return unless Parse::Pidl::Util::has_property($d, "public");
248 my $pull_args = $tf->{PULL_FN_ARGS}->($d);
249 my $push_args = $tf->{PUSH_FN_ARGS}->($d);
250 my $print_args = $tf->{PRINT_FN_ARGS}->($d);
251 unless (Parse::Pidl::Util::has_property($d, "nopush")) {
252 pidl "NTSTATUS ndr_push_$d->{NAME}($push_args);\n";
254 unless (Parse::Pidl::Util::has_property($d, "nopull")) {
255 pidl "NTSTATUS ndr_pull_$d->{NAME}($pull_args);\n";
257 unless (Parse::Pidl::Util::has_property($d, "noprint")) {
258 pidl "void ndr_print_$d->{NAME}($print_args);\n";
262 #####################################################################
267 if (!defined($const->{ARRAY_LEN}[0])) {
268 pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
270 pidl "#define $const->{NAME}\t $const->{VALUE}\n";
274 #####################################################################
276 sub HeaderFunctionInOut($$)
280 foreach my $e (@{$fn->{ELEMENTS}}) {
281 if (Parse::Pidl::Util::has_property($e, $prop)) {
287 #####################################################################
288 # determine if we need an "in" or "out" section
289 sub HeaderFunctionInOut_needed($$)
293 if ($prop eq "out" && $fn->{RETURN_TYPE}) {
297 foreach my $e (@{$fn->{ELEMENTS}}) {
298 if (Parse::Pidl::Util::has_property($e, $prop)) {
306 my %headerstructs = ();
308 #####################################################################
310 sub HeaderFunction($)
314 return if ($headerstructs{$fn->{NAME}});
316 $headerstructs{$fn->{NAME}} = 1;
318 pidl "\nstruct $fn->{NAME} {\n";
322 if (HeaderFunctionInOut_needed($fn, "in")) {
326 HeaderFunctionInOut($fn, "in");
333 if (HeaderFunctionInOut_needed($fn, "out")) {
337 HeaderFunctionInOut($fn, "out");
338 if ($fn->{RETURN_TYPE}) {
340 pidl Parse::Pidl::Typelist::mapType($fn->{RETURN_TYPE}) . " result;\n";
349 # sigh - some compilers don't like empty structures
351 pidl "int _dummy_element;\n";
358 #####################################################################
359 # output prototypes for a IDL function
360 sub HeaderFnProto($$)
362 my ($interface,$fn) = @_;
363 my $name = $fn->{NAME};
365 pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, const struct $name *r);\n";
367 if (defined($fn->{OPNUM})) {
368 pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
369 pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n";
372 return unless Parse::Pidl::Util::has_property($fn, "public");
374 pidl "NTSTATUS ndr_push_$name(struct ndr_push *ndr, int flags, const struct $name *r);\n";
375 pidl "NTSTATUS ndr_pull_$name(struct ndr_pull *ndr, int flags, struct $name *r);\n";
380 #####################################################################
381 # parse the interface definitions
382 sub HeaderInterface($)
384 my($interface) = shift;
388 pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n";
389 pidl "#define _HEADER_NDR_$interface->{NAME}\n\n";
391 if (defined $interface->{PROPERTIES}->{depends}) {
392 my @d = split / /, $interface->{PROPERTIES}->{depends};
394 pidl "#include \"librpc/gen_ndr/ndr_$i\.h\"\n";
398 if (defined $interface->{PROPERTIES}->{uuid}) {
399 my $name = uc $interface->{NAME};
400 pidl "#define DCERPC_$name\_UUID " .
401 Parse::Pidl::Util::make_str($interface->{PROPERTIES}->{uuid}) . "\n";
403 if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; }
404 pidl "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n";
406 pidl "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n";
408 if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; }
409 pidl "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n";
411 pidl "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
412 pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n";
415 foreach my $d (@{$interface->{FUNCTIONS}}) {
416 next if not defined($d->{OPNUM});
417 my $u_name = uc $d->{NAME};
418 pidl "#define DCERPC_$u_name (";
420 if (defined($interface->{BASE})) {
421 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
424 if ($d->{OPNUM} != $count) {
425 die ("Function ".$d->{NAME}." has: wrong opnum [".$d->{OPNUM}."] should be [".$count."]");
428 pidl sprintf("0x%02x", $count) . ")\n";
432 pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT (";
434 if (defined($interface->{BASE})) {
435 pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + ";
440 foreach my $d (@{$interface->{CONSTS}}) {
444 foreach my $d (@{$interface->{TYPEDEFS}}) {
446 HeaderTypedefProto($d);
449 foreach my $d (@{$interface->{FUNCTIONS}}) {
451 HeaderFnProto($interface, $d);
454 pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n";
457 #####################################################################
458 # parse a parsed IDL into a C header
465 pidl "/* header auto-generated by pidl */\n\n";
466 foreach my $x (@{$idl}) {
467 ($x->{TYPE} eq "INTERFACE") && HeaderInterface($x);