forgont genstruct.pl is needed to build new include files for genparse
authorSimo Sorce <idra@samba.org>
Mon, 16 Dec 2002 17:51:40 +0000 (17:51 +0000)
committerSimo Sorce <idra@samba.org>
Mon, 16 Dec 2002 17:51:40 +0000 (17:51 +0000)
sorry
(This used to be commit 4029dae9064e10a02006e9d0a5d8cf93e22eaed5)

source3/script/genstruct.pl [new file with mode: 0755]

diff --git a/source3/script/genstruct.pl b/source3/script/genstruct.pl
new file mode 100755 (executable)
index 0000000..e6d3077
--- /dev/null
@@ -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);