| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 | #!/usr/bin/perluse strict;use integer;use File::Basename;sub c_name($) {    my($s) = @_;    $s =~ s/[^A-Za-z0-9_]+/_/g;    return $s;}die "Usage: $0 infile hfile cfile\n" unless (scalar @ARGV >= 3);my($infile, $hfile, $cfile) = @ARGV;my $err = 0;open(my $in, '<', $infile) or die "$0: $infile: $!\n";my $ns;my %vars;my %nsprefix;my $line = 0;while (defined(my $l = <$in>)) {    $line++;    $l =~ s/^\s+//;    $l =~ s/\s+$//;    next if ($l =~ /^(\#.*)?$/);    if ($l =~ /^\@(\w+)(\s+([\w\.]+))?/) {	$ns = $1;	if (!defined($vars{$ns})) {	    $vars{$ns} = {};	}	$nsprefix{$ns} = $3;	next;    }    if (!defined{$ns}) {	print STDERR "$0:$infile:$line: variable without namespace\n";	$err++;	next;    }    my($var,$type,$defval) = split(/\s+/, $l);    if (!defined($type)) {	print STDERR "$0:$infile:$line: variable $var lacks type\n";	$err++;	next;    }    $vars{$ns}->{$var} = [$type, $defval];}close($in);exit 1 if ($err);my @nslist = sort keys(%vars);my %nsfirst;my %nscount;my @varname = (undef);my @varenum = ('sysvar_null');my %vartype = ('sysvar_null' => 'SYSVAR_NULLTYPE');my @vardef;my $cnt = 1;foreach my $ns (@nslist) {    $nsfirst{$ns} = $cnt;    foreach my $var (sort keys(%{$vars{$ns}})) {	my($type, $defval) = @{$vars{$ns}->{$var}};	push(@varname, $nsprefix{$ns}.$var);	my $ename = c_name($ns.'.'.$var);	push(@varenum, $ename);	$vartype{$ename} = "SYSVAR_TYPE(_$type)";	if (defined($defval)) {	    # Add mangling here if needed	    push(@vardef, "\t[$ename] = { .v_$type = $defval },\n");	}	$cnt++;    }    $nscount{$ns} = $cnt - $nsfirst{$ns};}open(my $h, '>', $hfile) or die "$0:$hfile: $!\n";my $htag = c_name(uc(basename($hfile)));print $h "#ifndef $htag\n";print $h "#define $htag\n\n";print $h "enum sysvar_ns_enum {\n";print $h map { "\tsysvar_ns_$_,\n" } @nslist;print $h "\tsysvar_nscount\n};\n\n";print $h "enum sysvar_enum {\n";print $h map { "\t$_,\n" } @varenum;print $h "\tsysvar_count\n};\n\n";push(@varenum, 'sysvar_count');print $h "\n";# Sometimes it is convenient to have this as a preprocessor symbolprint $h "#define SYSVAR_COUNT $cnt\n\n";print $h "extern_c const char * const sysvar_name[sysvar_count];\n";print $h "extern_c const sysvar_type_t sysvar_types[sysvar_count];\n";print $h "extern_c const sysvar_t sysvar_defval[sysvar_count];\n";print $h "extern_c sysvar_t sysvar_val[sysvar_count];\n";print $h "extern_c bool sysvar_isset[sysvar_count];\n\n";print $h "static inline sysvar_type_t sysvar_type(size_t var)\n";print $h "{\n";print $h "\tif (!__builtin_constant_p(var)) {\n";print $h "\t\tif(var >= (size_t)sysvar_count)\n";print $h "\t\t\treturn SYSVAR_NULLTYPE;\n";print $h "\t\telse\n";print $h "\t\t\treturn sysvar_types[var];\n";print $h "\t}\n\n";print $h "\tswitch(var) {\n";foreach my $v (@varenum) {    next unless (defined($vartype{$v}));    print $h "\t\tcase ", $v, ":\n";    print $h "\t\t\treturn ", $vartype{$v}, ";\n";}print $h "\t\tdefault:\n";print $h "\t\t\treturn SYSVAR_NULLTYPE;\n";print $h "\t};\n";print $h "}\n\n";print $h "#endif /* $htag */\n";close($h);open(my $c, '>', $cfile) or die "$0:$cfile: $!\n";print $c "#include \"sysvars.h\"\n\n";printf $c "const sysvar_ns_t sysvar_ns[%d] = {\n", scalar(@nslist)+1;foreach my $ns (@nslist) {    printf $c "\t{ \"%s\", %d },\n", $ns, $nsfirst{$ns}, $nscount{$ns};}printf $c "\t{ NULL, %d }\n", $cnt;printf $c "};\n";print $c "const char * const sysvar_name[$cnt] = {\n";print $c "\tNULL,\n";foreach my $ns (@nslist) {    print $c "\n\t/* ---- $ns ---- */\n";    my $v_end = $nsfirst{$ns} + $nscount{$ns};    for (my $v = $nsfirst{$ns}; $v < $v_end; $v++) {	print $c "\t\"", $varname[$v], "\",\n";    }}print $c "};\n";print $c "const sysvar_type_t sysvar_types[$cnt] = {\n";foreach my $v (@varenum) {    next unless (defined($vartype{$v}));    print $c "\t[$v] = ", $vartype{$v}, ",\n";}print $c "};\n";print $c "const sysvar_t sysvar_defval[$cnt] = {\n";print $c @vardef;print $c "};\n";print $c "sysvar_t sysvar_val[$cnt];\n";print $c "bool sysvar_isset[$cnt];\n";close($c);
 |