2 # a simple system for generating C parse info
3 # this can be used to write generic C structer load/save routines
4 # Copyright 2002 Andrew Tridgell <genstruct@tridgell.net>
5 # released under the GNU General Public License v2 or later
10 my(%struct_done) = ();
12 ###################################################
14 sub handle_general($$$$$$$$)
17 my($ptr_count) = shift;
22 my($parse_fn) = shift;
25 my($dynamic_len) = "NULL";
27 # handle arrays, currently treat multidimensional arrays as 1 dimensional
28 while ($element =~ /(.*)\[(.*?)\]$/) {
30 if ($array_len == 0) {
33 $array_len = "$2 * $array_len";
37 if ($flags =~ /_LEN\((\w*?)\)/) {
38 $dynamic_len = "\"$1\"";
41 if ($flags =~ /_NULLTERM/) {
42 $tflags = "FLAG_NULLTERM";
45 print OFILE "{\"$element\", $ptr_count, $size, offsetof(struct $name, $element), $array_len, $dynamic_len, $tflags, $dump_fn, $parse_fn},\n";
49 ####################################################
58 my($size) = "sizeof($type)";
61 # enums get the FLAG_ALWAYS flag
62 if ($type =~ /^enum /) {
63 $tflags = "FLAG_ALWAYS";
67 # make the pointer part of the base type
68 while ($element =~ /^\*(.*)/) {
76 my($dump_fn) = "gen_dump_$type";
77 my($parse_fn) = "gen_parse_$type";
79 handle_general($name, $ptr_count, $size, $element, $flags, $dump_fn, $parse_fn, $tflags);
82 ####################################################
84 sub parse_element($$$)
93 if ($element =~ /^struct (\S*) (.*)/) {
96 } elsif ($element =~ /^enum (\S*) (.*)/) {
99 } elsif ($element =~ /^unsigned (\S*) (.*)/) {
100 $type = "unsigned $1";
102 } elsif ($element =~ /^const (\S*) (.*)/) {
105 } elsif ($element =~ /^(\S*) (.*)/) {
109 die "Can't parse element '$element'";
112 # handle comma separated lists
113 while ($data =~ /(\S*),[\s]?(.*)/) {
114 parse_one($name, $type, $1, $flags);
117 parse_one($name, $type, $data, $flags);
121 my($first_struct) = 1;
123 ####################################################
124 # parse the elements of one structure
125 sub parse_elements($$)
128 my($elements) = shift;
132 print "Parsing structs: $name";
137 print OFILE "int gen_dump_struct_$name(struct parse_string *, const char *, unsigned);\n";
138 print OFILE "int gen_parse_struct_$name(char *, const char *);\n";
140 print OFILE "static const struct parse_struct pinfo_" . $name . "[] = {\n";
142 while ($elements =~ /^.*?([a-z].*?);\s*?(\S*?)\s*?$(.*)/msi) {
146 parse_element($name, $element, $flags);
149 print OFILE "{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}};\n";
152 int gen_dump_struct_$name(struct parse_string *p, const char *ptr, unsigned indent) {
153 return gen_dump_struct(pinfo_$name, p, ptr, indent);
155 int gen_parse_struct_$name(char *ptr, const char *str) {
156 return gen_parse_struct(pinfo_$name, ptr, str);
164 ####################################################
165 # parse out the enum declarations
166 sub parse_enum_elements($$)
169 my($elements) = shift;
173 print "Parsing enums: $name";
178 print OFILE "static const struct enum_struct einfo_" . $name . "[] = {\n";
180 my(@enums) = split(/,/s, $elements);
181 for (my($i)=0; $i <= $#enums; $i++) {
182 my($enum) = $enums[$i];
183 if ($enum =~ /\s*(\w*)/) {
185 print OFILE "{\"$e\", $e},\n";
189 print OFILE "{NULL, 0}};\n";
192 int gen_dump_enum_$name(struct parse_string *p, const char *ptr, unsigned indent) {
193 return gen_dump_enum(einfo_$name, p, ptr, indent);
196 int gen_parse_enum_$name(char *ptr, const char *str) {
197 return gen_parse_enum(einfo_$name, ptr, str);
203 ####################################################
204 # parse out the enum declarations
209 while ($data =~ /^GENSTRUCT\s+enum\s+(\w*?)\s*{(.*?)}\s*;(.*)/ms) {
214 if (!defined($enum_done{$name})) {
215 $enum_done{$name} = 1;
216 parse_enum_elements($name, $elements);
225 ####################################################
226 # parse all the structures
231 # parse into structures
232 while ($data =~ /^GENSTRUCT\s+struct\s+(\w+?)\s*{\s*(.*?)\s*}\s*;(.*)/ms) {
236 if (!defined($struct_done{$name})) {
237 $struct_done{$name} = 1;
238 parse_elements($name, $elements);
242 if (! $first_struct) {
245 print "No GENSTRUCT structures found?\n";
250 ####################################################
251 # parse a header file, generating a dumper structure
257 $data =~ s/[\t ]+/ /sg;
258 $data =~ s/\s*\n\s+/\n/sg;
260 $data =~ s/^\#.*?\n//smg;
263 parse_structs($data);
267 #########################################
272 generator for C structure dumpers
273 Copyright Andrew Tridgell <genstruct\@tridgell.net>
276 genstruct -o output.h gcc -E -O2 -g test.h
279 --help this help page
280 -o OUTPUT place output in OUTPUT
285 ########################################
287 if ($ARGV[0] ne "-o" || $#ARGV < 2) {
292 my($opt_ofile)=shift;
294 open(OFILE, ">$opt_ofile") || die "can't open $opt_ofile";
296 print OFILE "/* This is an automatically generated file - DO NOT EDIT! */\n\n";
298 parse_data(`@ARGV -DGENSTRUCT=GENSTRUCT`);