mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
299 lines
6.2 KiB
Perl
299 lines
6.2 KiB
Perl
|
#!/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);
|