blob: fdc7582f082355889b0001024079c580b6acb212 [file] [log] [blame]
#!/usr/bin/env perl
# *************************************************************
#
# usage: <this-script> [-list listfile] [-e] [-t] filename [filename]*
#
# -e generate enums and error messages
# -t generate #defines and error messages
#
# (both -e and -t can be used)
#
# -list: generate a list of error codes instead of other outputs
#
# *************************************************************
#
# INPUT: any number of sets of error codes for software
# layers called "name", with (unique) masks as follows:
#
# name = mask {
# ERRNAME Error string
# ERRNAME Error string
# ...
# ERRNAME Error string
# }
#
# (mask can be in octal (0777777), hex (0xabcdeff) or decimal
# notation)
#
# If you want the error_info[] structure to be part of a class,
# put the class name after the mask and groupname and before the open "{"
# for the group of error messages; in that case the <name>_einfo_gen.h
# file will look like:
# heron::error::error_info_t <class>::error_info[] = ...
# If you don't do that, the name of the error_info structure will
# have the <name> prepended, e.g.:
# heron::error::error_info_t <name>_error_info[] = ...
#
# *************************************************************
#
# OUTPUT:
# for each software layer ("name"), this script creates:
# <name>-errmsg-gen.h (-m)
# <name>-einfo-gen.h (-p)
# <name>-einfo-bakw-gen.h (-p)
# <name>-error-enum-gen.h (-e)
# <name>-error-def-gen.h (-d)
#
# name-error-gen.h contains a static char * array, each element is
# the error message associated with an error code
# name-einfo-gen.h contains a definition of a error_info_t array
# for use with the error package.
# name-error-gen.h contains an enumeration for the
# error codes , and an enum containing e_ERRMIN & e_ERRMAX
# name-error-def-gen.h contains the #defined constants for the error
# codes, and for minimum and maximum error codes
#
# *************************************************************
use strict;
use Getopt::Long;
sub Usage
{
my $progname = $0;
$progname =~ s/.*[\\\/]//;
print STDERR <<EOF;
Usage: $progname [-t] [-e] filename...
Generate C++ code representing error information from file.
You must specify one of -t or -e
--t generate #defines and error messages
--e generate enums and error messages
--help|h print this message and exit
--list generate list of error codes instead of other outputs
EOF
}
my %options = (m => 0, p => 0, e => 0, d => 0, help => 0, 'list' => '');
my @options = ("m!", "p!", "e!", "d!", "help|h", "list=s");
my $ok = GetOptions(\%options, @options);
$ok = 0 if $#ARGV == -1;
my $m = $options{m};
my $p = $options{p};
my $e = $options{e};
my $d = $options{d};
$ok = 0 if (!$m && !$p && !$e && !$d);
if (!$ok || $options{help}) {
Usage();
die(!$ok);
}
my ( $list, $listfile );
$list = 0;
$list = 1, $listfile = $options{'list'} if ( $options{'list'} ne '' );
my $timeStamp = localtime;
sub MakeStdHeader
{
my ($fileName, $baseName) = @_;
my $headerExclusionName = uc($baseName);
$headerExclusionName =~ tr/A-Z0-9/_/c;
my $header = <<EOF;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef $headerExclusionName
#define $headerExclusionName
/*
* DO NOT EDIT ---
* generated by $0 from $fileName
* generated on $timeStamp
*/
EOF
return $header;
}
sub GenErrorFiles
{
my ($fileName, $baseName, $base, $groupName, $className, $m, $p, $e, $d, @lines) = @_;
$className .= '::' if $className;
$base = oct($base) if $base =~ /^0/;
my $arrayPrefix = $className || "${baseName}_";
my $num = 0;
my $uBaseName = uc($baseName);
my $errorMsgName = "${baseName}-errmsg-gen.h";
my $errorInfoName = "${baseName}-einfo-gen.h";
my $errorEnumName = "${baseName}-error-enum-gen.h";
my $errorDefName = "${baseName}-error-def-gen.h";
my $errorInfoBakwName = "${baseName}-einfo-bakw-gen.h";
if ( ! $list ) {
open MSG_OUT, ">$errorMsgName" or die "Couldn't open $errorMsgName" if ($m);
open INFO_OUT, ">$errorInfoName" or die "Couldn't open $errorInfoName" if ($p);
open ENUM_OUT, ">$errorEnumName" or die "Couldn't open $errorEnumName" if ($e);
open DEF_OUT, ">$errorDefName" or die "Couldn't open $errorDefName" if ($d);
open INFOBAKW_OUT, ">$errorInfoBakwName" or die "Couldn't open $errorInfoBakwName" if ($p);
print MSG_OUT MakeStdHeader($fileName, $errorMsgName) if ($m);
print INFO_OUT MakeStdHeader($fileName, $errorInfoName) if ($p);
print ENUM_OUT MakeStdHeader($fileName, $errorEnumName) if ($e);
print DEF_OUT MakeStdHeader($fileName, $errorDefName) if ($d);
print INFOBAKW_OUT MakeStdHeader($fileName, $errorInfoBakwName) if ($p);
print MSG_OUT "static char* ${baseName}_errmsg[] = {\n" if ($m);
print INFO_OUT "heron::error::error_info_t ${arrayPrefix}error_info[] = {\n" if ($p);
print ENUM_OUT "enum {\n" if ($e);
print INFOBAKW_OUT "heron::error::error_info_t ${baseName}_error_info_bakw[] = {\n" if ($p);
}
foreach my $line (@lines) {
my ($tag, $msg);
if ($line =~ /\s*(\S*)\s*(.*)/) {
($tag, $msg) = ($1, $2);
chomp $msg;
} else {
die "bad line $line";
}
my $dTag = "${baseName}_$tag";
my $eTag = "${uBaseName}_$tag";
if ( $list ) {
print LIST sprintf("%s_%s = %s\n", $baseName, $tag, $num + 1);
} else {
print MSG_OUT sprintf("/* %-25s */ \"%s\",\n", $m ? $eTag : $dTag, $msg) if ($m);
print INFO_OUT sprintf(" { %-25s, \"%s\" },\n", $p ? $eTag : $dTag, $msg) if ($p);
print ENUM_OUT sprintf(" %-25s = 0x%x,\n", $eTag, $base + $num) if ($e);
print DEF_OUT sprintf("#define %-25s 0x%x\n", $dTag, $base + $num) if ($d);
print INFOBAKW_OUT " { $eTag, \"$eTag\" },\n" if ($p);
}
$num++;
}
$num--;
return if ( $list );
if ($m) {
print MSG_OUT <<EOF;
"dummy error code"
};
const ${baseName}_msg_size = $num;
#endif
EOF
}
print INFO_OUT "};\n\n" if ($p);
print INFO_OUT sprintf("const sp_uint32 %-25s = %d;", "${uBaseName}_ERRCNT", $num+1) if ($p);
print INFO_OUT "\n\n#endif\n" if ($p);
# print ENUM_OUT sprintf(" %-25s = 0x%x,\n", "${uBaseName}_OK", 0) if ($e);
print ENUM_OUT sprintf(" %-25s = 0x%x,\n", "${uBaseName}_ERRMIN", $base) if ($e);
print ENUM_OUT sprintf(" %-25s = 0x%x\n", "${uBaseName}_ERRMAX", $base + $num) if ($e);
print ENUM_OUT "};\n\n#endif\n" if ($e);
# print DEF_OUT sprintf("#define %-25s 0x%x\n", "${baseName}_OK", 0) if ($d);
print DEF_OUT sprintf("#define %-25s 0x%x\n", "${baseName}_ERRMIN", $base) if ($d);
print DEF_OUT sprintf("#define %-25s 0x%x\n", "${baseName}_ERRMAX", $base + $num) if ($d);
print DEF_OUT "\n#endif\n" if ($d);
print INFOBAKW_OUT "};\n\n#endif\n" if ($p);
close MSG_OUT, or die "Couldn't close $errorMsgName" if ($m);
close INFO_OUT, or die "Couldn't close $errorInfoName" if ($p);
close ENUM_OUT, or die "Couldn't close $errorEnumName" if ($e);
close DEF_OUT, or die "Couldn't close $errorDefName" if ($d);
close INFOBAKW_OUT, or die "Couldn't close $errorInfoBakwName" if ($p);
}
sub ProcessFile
{
my ($fileName, $m, $p, $e, $d) = @_;
my ($baseName, $base, $groupName, $className, @lines);
my $line;
open INFILE, "<$fileName" or die "Couldn't open $fileName";
while (defined($line = <INFILE>)) {
next if $line =~ /^\s*\#/ || $line =~ /^\s*$/;
if ($line =~ /^\s*(\S+)\s*=\s*([0-9A-Fa-fxX]+)\s*(".*")\s*(\S*)\s*{/) {
($baseName, $base, $groupName, $className) = ($1, $2, $3, $4);
} elsif ($line =~ /^\s*}/) {
GenErrorFiles($fileName, $baseName, $base, $groupName, $className, $m, $p, $e, $d, @lines);
undef $baseName;
undef $base;
undef $groupName;
undef $className;
undef @lines;
} else {
push @lines, $line;
}
}
die "missing }" if defined $baseName;
}
if ( $list ) {
open LIST, ">$listfile" or die "Couldn't open $listfile";
}
foreach my $file (@ARGV) {
ProcessFile($file, $m, $p, $e, $d);
}
close LIST if ( $list );