diff options
Diffstat (limited to 'source3/script')
-rwxr-xr-x | source3/script/genstruct.pl | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/source3/script/genstruct.pl b/source3/script/genstruct.pl new file mode 100755 index 00000000000..e6d30773d64 --- /dev/null +++ b/source3/script/genstruct.pl @@ -0,0 +1,298 @@ +#!/usr/bin/perl -w +# a simple system for generating C parse info +# this can be used to write generic C structer load/save routines +# Copyright 2002 Andrew Tridgell <genstruct@tridgell.net> +# released under the GNU General Public License v2 or later + +use strict; + +my(%enum_done) = (); +my(%struct_done) = (); + +################################################### +# general handler +sub handle_general($$$$$$$$) +{ + my($name) = shift; + my($ptr_count) = shift; + my($size) = shift; + my($element) = shift; + my($flags) = shift; + my($dump_fn) = shift; + my($parse_fn) = shift; + my($tflags) = shift; + my($array_len) = 0; + my($dynamic_len) = "NULL"; + + # handle arrays, currently treat multidimensional arrays as 1 dimensional + while ($element =~ /(.*)\[(.*?)\]$/) { + $element = $1; + if ($array_len == 0) { + $array_len = $2; + } else { + $array_len = "$2 * $array_len"; + } + } + + if ($flags =~ /_LEN\((\w*?)\)/) { + $dynamic_len = "\"$1\""; + } + + if ($flags =~ /_NULLTERM/) { + $tflags = "FLAG_NULLTERM"; + } + + print OFILE "{\"$element\", $ptr_count, $size, offsetof(struct $name, $element), $array_len, $dynamic_len, $tflags, $dump_fn, $parse_fn},\n"; +} + + +#################################################### +# parse one element +sub parse_one($$$$) +{ + my($name) = shift; + my($type) = shift; + my($element) = shift; + my($flags) = shift; + my($ptr_count) = 0; + my($size) = "sizeof($type)"; + my($tflags) = "0"; + + # enums get the FLAG_ALWAYS flag + if ($type =~ /^enum /) { + $tflags = "FLAG_ALWAYS"; + } + + + # make the pointer part of the base type + while ($element =~ /^\*(.*)/) { + $ptr_count++; + $element = $1; + } + + # convert spaces to _ + $type =~ s/ /_/g; + + my($dump_fn) = "gen_dump_$type"; + my($parse_fn) = "gen_parse_$type"; + + handle_general($name, $ptr_count, $size, $element, $flags, $dump_fn, $parse_fn, $tflags); +} + +#################################################### +# parse one element +sub parse_element($$$) +{ + my($name) = shift; + my($element) = shift; + my($flags) = shift; + my($type); + my($data); + + # pull the base type + if ($element =~ /^struct (\S*) (.*)/) { + $type = "struct $1"; + $data = $2; + } elsif ($element =~ /^enum (\S*) (.*)/) { + $type = "enum $1"; + $data = $2; + } elsif ($element =~ /^unsigned (\S*) (.*)/) { + $type = "unsigned $1"; + $data = $2; + } elsif ($element =~ /^(\S*) (.*)/) { + $type = $1; + $data = $2; + } else { + die "Can't parse element '$element'"; + } + + # handle comma separated lists + while ($data =~ /(\S*),[\s]?(.*)/) { + parse_one($name, $type, $1, $flags); + $data = $2; + } + parse_one($name, $type, $data, $flags); +} + + +my($first_struct) = 1; + +#################################################### +# parse the elements of one structure +sub parse_elements($$) +{ + my($name) = shift; + my($elements) = shift; + + if ($first_struct) { + $first_struct = 0; + print "Parsing structs: $name"; + } else { + print ", $name"; + } + + print OFILE "int gen_dump_struct_$name(struct parse_string *, const char *, unsigned);\n"; + print OFILE "int gen_parse_struct_$name(char *, const char *);\n"; + + print OFILE "static const struct parse_struct pinfo_" . $name . "[] = {\n"; + + while ($elements =~ /^.*?([a-z].*?);\s*?(\S*?)\s*?$(.*)/msi) { + my($element) = $1; + my($flags) = $2; + $elements = $3; + parse_element($name, $element, $flags); + } + + print OFILE "{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}};\n"; + + print OFILE " +int gen_dump_struct_$name(struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_struct(pinfo_$name, p, ptr, indent); +} +int gen_parse_struct_$name(char *ptr, const char *str) { + return gen_parse_struct(pinfo_$name, ptr, str); +} + +"; +} + +my($first_enum) = 1; + +#################################################### +# parse out the enum declarations +sub parse_enum_elements($$) +{ + my($name) = shift; + my($elements) = shift; + + if ($first_enum) { + $first_enum = 0; + print "Parsing enums: $name"; + } else { + print ", $name"; + } + + print OFILE "static const struct enum_struct einfo_" . $name . "[] = {\n"; + + my(@enums) = split(/,/s, $elements); + for (my($i)=0; $i <= $#{@enums}; $i++) { + my($enum) = $enums[$i]; + if ($enum =~ /\s*(\w*)/) { + my($e) = $1; + print OFILE "{\"$e\", $e},\n"; + } + } + + print OFILE "{NULL, 0}};\n"; + + print OFILE " +int gen_dump_enum_$name(struct parse_string *p, const char *ptr, unsigned indent) { + return gen_dump_enum(einfo_$name, p, ptr, indent); +} + +int gen_parse_enum_$name(char *ptr, const char *str) { + return gen_parse_enum(einfo_$name, ptr, str); +} + +"; +} + +#################################################### +# parse out the enum declarations +sub parse_enums($) +{ + my($data) = shift; + + while ($data =~ /^GENSTRUCT\s+enum\s+(\w*?)\s*{(.*?)}\s*;(.*)/ms) { + my($name) = $1; + my($elements) = $2; + $data = $3; + + if (!defined($enum_done{$name})) { + $enum_done{$name} = 1; + parse_enum_elements($name, $elements); + } + } + + if (! $first_enum) { + print "\n"; + } +} + +#################################################### +# parse all the structures +sub parse_structs($) +{ + my($data) = shift; + + # parse into structures + while ($data =~ /^GENSTRUCT\s+struct\s+(\w+?)\s*{\s*(.*?)\s*}\s*;(.*)/ms) { + my($name) = $1; + my($elements) = $2; + $data = $3; + if (!defined($struct_done{$name})) { + $struct_done{$name} = 1; + parse_elements($name, $elements); + } + } + + if (! $first_struct) { + print "\n"; + } else { + print "No GENSTRUCT structures found?\n"; + } +} + + +#################################################### +# parse a header file, generating a dumper structure +sub parse_data($) +{ + my($data) = shift; + + # collapse spaces + $data =~ s/[\t ]+/ /sg; + $data =~ s/\s*\n\s+/\n/sg; + # strip debug lines + $data =~ s/^\#.*?\n//smg; + + parse_enums($data); + parse_structs($data); +} + + +######################################### +# display help text +sub ShowHelp() +{ + print " +generator for C structure dumpers +Copyright Andrew Tridgell <genstruct\@tridgell.net> + +Sample usage: + genstruct -o output.h gcc -E -O2 -g test.h + +Options: + --help this help page + -o OUTPUT place output in OUTPUT +"; + exit(0); +} + +######################################## +# main program +if ($ARGV[0] ne "-o" || $#ARGV < 2) { + ShowHelp(); +} + +shift; +my($opt_ofile)=shift; + +print "creating $opt_ofile\n"; + +open(OFILE, ">$opt_ofile") || die "can't open $opt_ofile"; + +print OFILE "/* This is an automatically generated file - DO NOT EDIT! */\n\n"; + +parse_data(`@ARGV -DGENSTRUCT=GENSTRUCT`); +exit(0); |