Use more stricter syntax and work towards Docbook XML migration
[Samba/gebeck_regimport.git] / source3 / script / genstruct.pl
bloba6abd718c959fea569abca29bc40b967848893d4
1 #!/usr/bin/perl -w
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
7 use strict;
9 my(%enum_done) = ();
10 my(%struct_done) = ();
12 ###################################################
13 # general handler
14 sub handle_general($$$$$$$$)
16 my($name) = shift;
17 my($ptr_count) = shift;
18 my($size) = shift;
19 my($element) = shift;
20 my($flags) = shift;
21 my($dump_fn) = shift;
22 my($parse_fn) = shift;
23 my($tflags) = shift;
24 my($array_len) = 0;
25 my($dynamic_len) = "NULL";
27 # handle arrays, currently treat multidimensional arrays as 1 dimensional
28 while ($element =~ /(.*)\[(.*?)\]$/) {
29 $element = $1;
30 if ($array_len == 0) {
31 $array_len = $2;
32 } else {
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 ####################################################
50 # parse one element
51 sub parse_one($$$$)
53 my($name) = shift;
54 my($type) = shift;
55 my($element) = shift;
56 my($flags) = shift;
57 my($ptr_count) = 0;
58 my($size) = "sizeof($type)";
59 my($tflags) = "0";
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 =~ /^\*(.*)/) {
69 $ptr_count++;
70 $element = $1;
73 # convert spaces to _
74 $type =~ s/ /_/g;
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 ####################################################
83 # parse one element
84 sub parse_element($$$)
86 my($name) = shift;
87 my($element) = shift;
88 my($flags) = shift;
89 my($type);
90 my($data);
92 # pull the base type
93 if ($element =~ /^struct (\S*) (.*)/) {
94 $type = "struct $1";
95 $data = $2;
96 } elsif ($element =~ /^enum (\S*) (.*)/) {
97 $type = "enum $1";
98 $data = $2;
99 } elsif ($element =~ /^unsigned (\S*) (.*)/) {
100 $type = "unsigned $1";
101 $data = $2;
102 } elsif ($element =~ /^(\S*) (.*)/) {
103 $type = $1;
104 $data = $2;
105 } else {
106 die "Can't parse element '$element'";
109 # handle comma separated lists
110 while ($data =~ /(\S*),[\s]?(.*)/) {
111 parse_one($name, $type, $1, $flags);
112 $data = $2;
114 parse_one($name, $type, $data, $flags);
118 my($first_struct) = 1;
120 ####################################################
121 # parse the elements of one structure
122 sub parse_elements($$)
124 my($name) = shift;
125 my($elements) = shift;
127 if ($first_struct) {
128 $first_struct = 0;
129 print "Parsing structs: $name";
130 } else {
131 print ", $name";
134 print OFILE "int gen_dump_struct_$name(TALLOC_CTX *mem_ctx, struct parse_string *, const char *, unsigned);\n";
135 print OFILE "int gen_parse_struct_$name(TALLOC_CTX *mem_ctx, char *, const char *);\n";
137 print OFILE "static const struct parse_struct pinfo_" . $name . "[] = {\n";
140 while ($elements =~ /^.*?([a-z].*?);\s*?(\S*?)\s*?$(.*)/msi) {
141 my($element) = $1;
142 my($flags) = $2;
143 $elements = $3;
144 parse_element($name, $element, $flags);
147 print OFILE "{NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL}};\n";
149 print OFILE "
150 int gen_dump_struct_$name(TALLOC_CTX *mem_ctx, struct parse_string *p, const char *ptr, unsigned indent) {
151 return gen_dump_struct(mem_ctx, pinfo_$name, p, ptr, indent);
153 int gen_parse_struct_$name(TALLOC_CTX *mem_ctx, char *ptr, const char *str) {
154 return gen_parse_struct(mem_ctx, pinfo_$name, ptr, str);
160 my($first_enum) = 1;
162 ####################################################
163 # parse out the enum declarations
164 sub parse_enum_elements($$)
166 my($name) = shift;
167 my($elements) = shift;
169 if ($first_enum) {
170 $first_enum = 0;
171 print "Parsing enums: $name";
172 } else {
173 print ", $name";
176 print OFILE "static const struct enum_struct einfo_" . $name . "[] = {\n";
178 my(@enums) = split(/,/s, $elements);
179 for (my($i)=0; $i <= $#{@enums}; $i++) {
180 my($enum) = $enums[$i];
181 if ($enum =~ /\s*(\w*)/) {
182 my($e) = $1;
183 print OFILE "{\"$e\", $e},\n";
187 print OFILE "{NULL, 0}};\n";
189 print OFILE "
190 int gen_dump_enum_$name(struct parse_string *p, const char *ptr, unsigned indent) {
191 return gen_dump_enum(einfo_$name, p, ptr, indent);
194 int gen_parse_enum_$name(char *ptr, const char *str) {
195 return gen_parse_enum(einfo_$name, ptr, str);
201 ####################################################
202 # parse out the enum declarations
203 sub parse_enums($)
205 my($data) = shift;
207 while ($data =~ /^GENSTRUCT\s+enum\s+(\w*?)\s*{(.*?)}\s*;(.*)/ms) {
208 my($name) = $1;
209 my($elements) = $2;
210 $data = $3;
212 if (!defined($enum_done{$name})) {
213 $enum_done{$name} = 1;
214 parse_enum_elements($name, $elements);
218 if (! $first_enum) {
219 print "\n";
223 ####################################################
224 # parse all the structures
225 sub parse_structs($)
227 my($data) = shift;
229 # parse into structures
230 while ($data =~ /^GENSTRUCT\s+struct\s+(\w+?)\s*{\s*(.*?)\s*}\s*;(.*)/ms) {
231 my($name) = $1;
232 my($elements) = $2;
233 $data = $3;
234 if (!defined($struct_done{$name})) {
235 $struct_done{$name} = 1;
236 parse_elements($name, $elements);
240 if (! $first_struct) {
241 print "\n";
242 } else {
243 print "No GENSTRUCT structures found?\n";
248 ####################################################
249 # parse a header file, generating a dumper structure
250 sub parse_data($)
252 my($data) = shift;
254 # collapse spaces
255 $data =~ s/[\t ]+/ /sg;
256 $data =~ s/\s*\n\s+/\n/sg;
257 # strip debug lines
258 $data =~ s/^\#.*?\n//smg;
260 parse_enums($data);
261 parse_structs($data);
265 #########################################
266 # display help text
267 sub ShowHelp()
269 print "
270 generator for C structure dumpers
271 Copyright Andrew Tridgell <genstruct\@tridgell.net>
273 Sample usage:
274 genstruct -o output.h gcc -E -O2 -g test.h
276 Options:
277 --help this help page
278 -o OUTPUT place output in OUTPUT
280 exit(0);
283 ########################################
284 # main program
285 if ($ARGV[0] ne "-o" || $#ARGV < 2) {
286 ShowHelp();
289 shift;
290 my($opt_ofile)=shift;
292 print "creating $opt_ofile\n";
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`);
299 exit(0);