#!/usr/bin/perl -w use strict; use XML::DOM; sub write_c_header(@); sub write_sql_dump(@); sub get_data($); my $dump_to_sql = 0; # initialize parser and read the file my $input = "./config.xml"; my $parser = new XML::DOM::Parser; my $tree = $parser->parsefile($input) || die "Unable to parse XML file."; # Get data my $nodes = $tree->getElementsByTagName("option"); my @options = (); for (my $i = 0; $i < $nodes->getLength; $i++) { my @data = get_data($nodes->item($i)); push @options, \@data; } write_c_header(@options); write_sql_dump(@options) if ($dump_to_sql); my $config_defaults = "void config_defaults(struct hub_config* config)\n{\n"; my $config_apply = "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n"; my $config_free = "void free_config(struct hub_config* config)\n{\n"; my $config_dump = "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n"; foreach my $option (@options) { my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check) = @$option; my $string = ($type =~ /(string|file|message)/); my $min = undef; my $max = undef; my $regexp = undef; if (defined $check) { $min = $check->getAttribute("min"); $max = $check->getAttribute("max"); $regexp = $check->getAttribute("regexp"); $max = undef if ($max eq ""); $min = undef if ($min eq ""); $regexp = undef if ($regexp eq ""); } $config_defaults .= "\tconfig->$name = "; $config_defaults .= "hub_strdup(\"" if ($string); $config_defaults .= $default; $config_defaults .= "\")" if ($string); $config_defaults .= ";\n"; $config_apply .= "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n"; if ($type eq "int") { $config_apply .= "\t\tmin = $min;\n" if (defined $min); $config_apply .= "\t\tmax = $max;\n" if (defined $max); $config_apply .= "\t\tif (!apply_integer(key, data, &config->$name, "; if (defined $min) { $config_apply .= "&min"; } else { $config_apply .= "0"; } $config_apply .= ", "; if (defined $max) { $config_apply .= "&max"; } else { $config_apply .= "0"; } $config_apply .= "))\n"; } elsif ($type eq "boolean") { $config_apply .= "\t\tif (!apply_boolean(key, data, &config->$name))\n"; } elsif ($string) { $config_apply .="\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n"; } $config_apply .= "\t\t{\n" . "\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" . "\t\t\treturn -1;\n" . "\t\t}\n" . "\t\treturn 0;\n" . "\t}\n\n"; $config_free .= "\thub_free(config->" . $name . ");\n\n" if ($string); my $out = "%s"; my $val = "config->$name"; my $test = "config->$name != $default"; $out = "%d" if ($type eq "int"); $val = "config->$name ? \"yes\" : \"no\"" if ($type eq "boolean"); if ($string) { $out = "\\\"%s\\\""; $test = "strcmp(config->$name, \"$default\") != 0"; } $config_dump .= "\tif (!ignore_defaults || $test)\n"; $config_dump .= "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n"; } $config_apply .= "\t/* Still here -- unknown directive */\n"; $config_apply .= "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n"; $config_apply .= "\treturn -1;\n"; $config_apply .= "}\n\n"; $config_defaults .= "}\n\n"; $config_free .= "}\n\n"; $config_dump .= "}\n\n"; open GENIMPL, ">gen_config.c" || die "Unable to write source file"; print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n"; print GENIMPL $config_defaults; print GENIMPL $config_apply; print GENIMPL $config_free; print GENIMPL $config_dump; sub get_data($) { my $p = shift; my $short = ""; my $example = ""; my $description = ""; my $since = ""; $short = $p->getElementsByTagName("short")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("short")->getLength()); $since = $p->getElementsByTagName("since")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("since")->getLength()); $example = $p->getElementsByTagName("example")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("example")->getLength()); $description = $p->getElementsByTagName("description")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("description")->getLength()); my $check = $p->getElementsByTagName("check")->item(0); my @data = ( $p->getAttribute("type"), $p->getAttribute("name"), $p->getAttribute("default"), $p->getAttribute("advanced"), $short, $description, $since, $example, $check ); return @data; } # Write header file sub write_c_header(@) { my @data = @_; open GENHEAD, ">gen_config.h" || die "Unable to write header file"; print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n"; print GENHEAD "struct hub_config\n{\n"; foreach my $option (@data) { my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @$option; my $string = ($type =~ /(string|file|message)/); print GENHEAD "\t"; print GENHEAD "int " if ($type eq "int"); print GENHEAD "int " if ($type eq "boolean"); print GENHEAD "char*" if ($string); print GENHEAD " " . $name . ";"; my $comment = ""; if ($type eq "message") { $comment = "\"" . $default . "\""; } elsif (defined $short && length $short > 0) { $comment = $short; if (defined $default) { $comment .= " (default: "; $comment .= "\"" if ($string); $comment .= $default; $comment .= "\"" if ($string); $comment .= ")"; } } if (length $comment > 0) { my $pad = ""; for (my $i = length $name; $i < 32; $i++) { $pad .= " "; } $comment = $pad . "/*<<< " . $comment . " */"; } print GENHEAD $comment . "\n"; } print GENHEAD "};\n\n"; } sub write_sql_dump(@) { my @data = @_; # Write SQL dump code open GENSQL, ">gen_config.sql" || die "Unable to write SQL dump"; print GENSQL "START TRANSACTION;\n\n DROP TABLE uhub_config IF EXISTS;\n\n CREATE TABLE uhub_config ( name VARCHAR(32) UNIQUE NOT NULL, defaultValue TINYTEXT NOT NULL, description LONGTEXT NOT NULL, type TINYTEXT NOT NULL, advanced BOOLEAN, example LONGTEXT, since TINYTEXT );\n\n"; foreach my $option (@data) { my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @$option; if ($type =~ /(string|file|message)/ ) { $default = "\\\"$default\\\""; } $desc =~ s/\"/\\\"/g; $type =~ s/^int$/integer/; my $stmt = "INSERT INTO uhub_config VALUES("; $stmt .= "\"$name\", "; $stmt .= "\"$default\", "; $stmt .= "\"$desc\", "; $stmt .= "\"$type\", "; if (defined $example) { my $example_str = $example; $example_str =~ s/\\/\\\\/g; $example_str =~ s/\"/\\\"/g; $stmt .= "\"$example_str\", "; } else { $stmt .= "NULL, "; } if (defined $since) { $stmt .= "\"$since\", "; } else { $stmt .= "NULL, "; } if (defined $advanced) { $stmt .= "\"$advanced\""; } else { $stmt .= "NULL"; } $stmt .= ");\n"; print GENSQL $stmt; } print GENSQL "\n\nCOMMIT;\n\n"; }