Blame MakeTools/buildmsgs.pl

Packit 857059
#! perl -w
Packit 857059
# BEGIN_ICS_COPYRIGHT8 ****************************************
Packit 857059
# 
Packit 857059
# Copyright (c) 2015, Intel Corporation
Packit 857059
# 
Packit 857059
# Redistribution and use in source and binary forms, with or without
Packit 857059
# modification, are permitted provided that the following conditions are met:
Packit 857059
# 
Packit 857059
#     * Redistributions of source code must retain the above copyright notice,
Packit 857059
#       this list of conditions and the following disclaimer.
Packit 857059
#     * Redistributions in binary form must reproduce the above copyright
Packit 857059
#       notice, this list of conditions and the following disclaimer in the
Packit 857059
#       documentation and/or other materials provided with the distribution.
Packit 857059
#     * Neither the name of Intel Corporation nor the names of its contributors
Packit 857059
#       may be used to endorse or promote products derived from this software
Packit 857059
#       without specific prior written permission.
Packit 857059
# 
Packit 857059
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 857059
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 857059
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 857059
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit 857059
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 857059
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit 857059
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit 857059
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit 857059
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 857059
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 857059
# 
Packit 857059
# END_ICS_COPYRIGHT8   ****************************************
Packit 857059
Packit 857059
#
Packit 857059
# Converts a message file to a pair of C files (a source file and a header)
Packit 857059
# that define macros and data structures for use with the Err module for error
Packit 857059
# reporting.
Packit 857059
#
Packit 857059
# If you encounter any problems with this program please notify Frank Szczerba
Packit 857059
# (fszczerba@infiniconsys.com).
Packit 857059
#
Packit 857059
Packit 857059
use strict;
Packit 857059
use integer;
Packit 857059
use FileHandle;
Packit 857059
use File::Basename;
Packit 857059
Packit 857059
# list of supported languages ( LOG_LANG_ is prepended on output ) must be uppercase
Packit 857059
my @languages = qw( ENGLISH );
Packit 857059
Packit 857059
#### end configuration
Packit 857059
my %languages;	# @languages by name
Packit 857059
for (my $i = 0; $i < scalar(@languages); $i++) {
Packit 857059
	$languages{$languages[$i]} = $i;
Packit 857059
}
Packit 857059
Packit 857059
my $msgFile;
Packit 857059
my $msgFileLine;
Packit 857059
my $warnCount = 0;
Packit 857059
my $errorCount = 0;
Packit 857059
my $context;
Packit 857059
my $testMode = 0;
Packit 857059
Packit 857059
sub output {
Packit 857059
	my $level = shift;
Packit 857059
	my $out = $testMode ? *STDOUT : *STDERR;
Packit 857059
	print $out ("$msgFile:$msgFileLine: $level: ",
Packit 857059
		  defined $context ? "$context: ": "", @_, "\n");
Packit 857059
}
Packit 857059
Packit 857059
sub warning {
Packit 857059
	output "WARNING", @_;
Packit 857059
	$warnCount++;
Packit 857059
}
Packit 857059
Packit 857059
sub error {
Packit 857059
	output "ERROR", @_;
Packit 857059
	$errorCount++;
Packit 857059
}
Packit 857059
Packit 857059
my $defModName;
Packit 857059
Packit 857059
sub validate_format($);
Packit 857059
sub get_names(\%);
Packit 857059
Packit 857059
#
Packit 857059
# file format definition
Packit 857059
#
Packit 857059
# All sections and attributes should be ucfirst(lower($_)) case
Packit 857059
#
Packit 857059
my $Format = {
Packit 857059
	File => {				# default scope
Packit 857059
	},
Packit 857059
	Module => {
Packit 857059
		Singular => 1,
Packit 857059
		Attributes => {
Packit 857059
			Name => { Required => 1, Type => "Ident", Min => 1},
Packit 857059
			Ucname => { Type => "UcIdent", Calculate => sub { uc $_[0]->{Name}; } },
Packit 857059
		},
Packit 857059
		Calculate => sub { {Name => $defModName}; },
Packit 857059
	},
Packit 857059
	Message => {
Packit 857059
		Key => "Name",
Packit 857059
		Attributes => {
Packit 857059
			Name => { Required => 1, Type => "UcIdent" },
Packit 857059
			Comment => { },
Packit 857059
			Arglist => { Type => "CSV", Max => 6 },
Packit 857059
			Unitarg => { Type => "Int", Min => 0, Max => 6, Default => 0, },
Packit 857059
			Trapfunc => { Type => "Ident", Default => "LOG_TRAP_NONE" },
Packit 857059
			Severity => {
Packit 857059
				Recomended => 1,
Packit 857059
				Type => "Picklist",
Packit 857059
				Transform => sub { $_[0] =~ tr/ /_/;
Packit 857059
								   $_[0] =~ s/PARTIAL/ADD_PART/; },
Packit 857059
				Set => "Class",
Packit 857059
				# Class is set to the RHS below:
Packit 857059
				Values => {
Packit 857059
					ADD_PART => "LOG_PART",
Packit 857059
					ALARM => "LOG_FINAL",
Packit 857059
					ERROR => "LOG_FINAL",
Packit 857059
					WARNING => "LOG_FINAL",
Packit 857059
					FATAL => "LOG_FINAL",
Packit 857059
					DUMP => "LOG",
Packit 857059
					CONFIG => "LOG",
Packit 857059
					PROGRAM_INFO => "LOG",
Packit 857059
					PERIODIC_INFO => "LOG",
Packit 857059
					DEBUG1_INFO => "LOG",
Packit 857059
					DEBUG2_INFO => "LOG",
Packit 857059
					DEBUG3_INFO => "LOG",
Packit 857059
					DEBUG4_INFO => "LOG",
Packit 857059
					DEBUG5_INFO => "LOG",
Packit 857059
                                        NOTICE => "LOG_FINAL",
Packit 857059
				},
Packit 857059
			},
Packit 857059
			Description => {
Packit 857059
				Required => 1,
Packit 857059
				Type => "FmtStr",
Packit 857059
				i18n => 1,
Packit 857059
			},
Packit 857059
			Response => {
Packit 857059
				i18n => 1,
Packit 857059
				Type => "FmtStr",
Packit 857059
				Default => "NULL",
Packit 857059
			},
Packit 857059
			Correction => {
Packit 857059
				i18n => 1,
Packit 857059
				Type => "FmtStr",
Packit 857059
				Default => "NULL",
Packit 857059
			},
Packit 857059
		},
Packit 857059
	},
Packit 857059
	String => {
Packit 857059
		Key => "Name",
Packit 857059
		Attributes => {
Packit 857059
			Name => { Required => 1, Type => "UcIdent" },
Packit 857059
			Comment => { },
Packit 857059
			Arglist => { Type => "CSV", Max => 6 },
Packit 857059
			String => {
Packit 857059
				Required => 1,
Packit 857059
				Type => "FmtStr",
Packit 857059
				i18n => 1,
Packit 857059
			},
Packit 857059
		},
Packit 857059
	}
Packit 857059
};
Packit 857059
Packit 857059
my $File = {};		# the master object
Packit 857059
my $object = {};	# temp object
Packit 857059
Packit 857059
{
Packit 857059
	my $scope = 'File';
Packit 857059
Packit 857059
	#
Packit 857059
	# Completes and validates and object and adds it to $File
Packit 857059
	#
Packit 857059
	sub new_scope($) {
Packit 857059
		VALIDATE_OBJ: {
Packit 857059
			# validate the object
Packit 857059
			#print "new_scope: $scope -> $_[0]\n";
Packit 857059
			foreach my $attr (keys(%{$Format->{$scope}{Attributes}})) {
Packit 857059
				my $def = $Format->{$scope}{Attributes}{$attr};
Packit 857059
Packit 857059
				if (not defined $object->{$attr}) {
Packit 857059
					if ($def->{Required}) {
Packit 857059
						error "Missing $attr attribute";
Packit 857059
						last VALIDATE_OBJ;
Packit 857059
					}
Packit 857059
					else {
Packit 857059
						if ($def->{Recomended}) {
Packit 857059
							warning "Missing $attr attribute";
Packit 857059
						}
Packit 857059
						if (defined $def->{Default} or defined $def->{Calculate}) {
Packit 857059
							my $default = defined $def->{Default} ? $def->{Default}
Packit 857059
																  : &{$def->{Calculate}}($object);
Packit 857059
							if ($def->{i18n}) {
Packit 857059
								# set default for all languages
Packit 857059
								$object->{$attr} = {};
Packit 857059
								foreach my $lang (@languages) {
Packit 857059
									$object->{$attr}{$lang} = $default;
Packit 857059
								}
Packit 857059
							}
Packit 857059
							else {
Packit 857059
								# set default
Packit 857059
								$object->{$attr} = $default;
Packit 857059
							}
Packit 857059
						}
Packit 857059
					}
Packit 857059
				}
Packit 857059
				elsif ($def->{i18n}) {
Packit 857059
					# if a message is provided for one language, it must be provided for all
Packit 857059
					foreach my $lang (@languages) {
Packit 857059
						if (not $object->{$attr}{$lang}) {
Packit 857059
							error "$attr: Missing $lang translation";
Packit 857059
							last VALIDATE_OBJ;
Packit 857059
						}
Packit 857059
					}
Packit 857059
				}
Packit 857059
			}
Packit 857059
Packit 857059
			if (defined $object->{FmtArgs}) {
Packit 857059
				my $numArgs = $object->{FmtArgs};
Packit 857059
				if (not defined $object->{Arglist}) {
Packit 857059
					error "Missing Arglist ($numArgs args used)";
Packit 857059
				}
Packit 857059
				else {
Packit 857059
					my $listLen = scalar(@{$object->{Arglist}});
Packit 857059
					if (defined $Format->{$scope}{Attributes}{Unitarg} and $object->{Unitarg} > $listLen) {
Packit 857059
						error "Insufficient arguments ($listLen) for UnitArg ($object->{Unitarg})";
Packit 857059
					}
Packit 857059
					if ($numArgs > $listLen) {
Packit 857059
						error "Insufficient arguments ($listLen) for format ($numArgs args used)";
Packit 857059
					}
Packit 857059
					elsif ($numArgs < $listLen) {
Packit 857059
						warning "Extra arguments ($listLen) for format ($numArgs args used)";
Packit 857059
					}
Packit 857059
					# check argument names
Packit 857059
					get_names(%$object);
Packit 857059
				}
Packit 857059
			}
Packit 857059
			if ($Format->{$scope}{Singular}) {
Packit 857059
				$File->{$scope} = $object;
Packit 857059
			}
Packit 857059
			else {
Packit 857059
				if (not exists $File->{$scope}) {
Packit 857059
					$File->{$scope} = [];
Packit 857059
				}
Packit 857059
				elsif ($Format->{$scope}{Key}) {
Packit 857059
					my $key = $Format->{$scope}{Key};
Packit 857059
					foreach my $exist (@{$File->{$scope}}) {
Packit 857059
						if ($exist->{$key} eq $object->{$key}) {
Packit 857059
							error "Duplicate $scope definition with $key=$object->{$key}";
Packit 857059
							last VALIDATE_OBJ;
Packit 857059
						}
Packit 857059
					}
Packit 857059
				}
Packit 857059
				push @{$File->{$scope}}, $object;
Packit 857059
			}
Packit 857059
		}	# VALIDATE_OBJ
Packit 857059
		$object = {};
Packit 857059
		$scope = $_[0];
Packit 857059
		$context = $scope;
Packit 857059
	}
Packit 857059
Packit 857059
	#
Packit 857059
	# Parser
Packit 857059
	#
Packit 857059
	sub parse_line($) {
Packit 857059
		my $line = $_[0];
Packit 857059
Packit 857059
		#print "$scope: $line\n";
Packit 857059
		# parse the line
Packit 857059
		LINE: for ($line) {
Packit 857059
			# attribute assignement
Packit 857059
			/^(\w+)(?:.(\w+))?\s*=\s*(.*)$/ and do {
Packit 857059
				my $attr = ucfirst lc $1;
Packit 857059
				my $lang;
Packit 857059
				my $val = $3;
Packit 857059
Packit 857059
				if (defined $2) {
Packit 857059
					$lang = uc $2;
Packit 857059
					if (not defined $languages{$lang}) {
Packit 857059
						error "Unknown language '$lang'";
Packit 857059
						last;
Packit 857059
					}
Packit 857059
				}
Packit 857059
Packit 857059
				if (not exists $Format->{$scope}{Attributes}{$attr}) {
Packit 857059
					error "Unknown attribute $attr for section $scope";
Packit 857059
					last;
Packit 857059
				}
Packit 857059
Packit 857059
				my $def = $Format->{$scope}{Attributes}{$attr};
Packit 857059
Packit 857059
				# type and range check
Packit 857059
				for ($def->{Type} ? $def->{Type} : "Str") {
Packit 857059
					/Int/	and do {
Packit 857059
						if ($val !~ /^\d*$/) {
Packit 857059
							error "Non-integer value $val for $attr";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						elsif (defined $def->{Min} and $val < $def->{Min}) {
Packit 857059
							error "$attr must be >= $def->{Min}";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						elsif (defined $def->{Max} and $val > $def->{Max}) {
Packit 857059
							error "$attr must be <= $def->{Max}";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						last;
Packit 857059
					};
Packit 857059
					/CSV/	and do {
Packit 857059
						# convert to a list ref
Packit 857059
						$val = [split /\s*,\s*/, $val];
Packit 857059
Packit 857059
						if (defined $def->{Min} and scalar(@$val) < $def->{Min}) {
Packit 857059
							error "$attr must be at least $def->{Min} element(s)";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						elsif (defined $def->{Max} and scalar(@$val) > $def->{Max}) {
Packit 857059
							error "$attr must be no more than $def->{Max} elements";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						last;
Packit 857059
					};
Packit 857059
					/CStr|FmtStr/ and do {
Packit 857059
						# strip continuation sequences
Packit 857059
						$val =~ s/([^\\])(?:"\s*")+/$1/g;
Packit 857059
						# and validate
Packit 857059
						if ($val !~ /^"(?:[^"\\]*|\\.)*"$/) {
Packit 857059
							error "$attr must be a double-quoted C string";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						# Use Str length check for now, but it will over-count escape sequences
Packit 857059
						# and the quotes
Packit 857059
Packit 857059
						# Fallthrough
Packit 857059
					};
Packit 857059
					/FmtStr/ and do {
Packit 857059
						my $numArgs = validate_format($val);
Packit 857059
						$object->{FmtArgs} = $numArgs if (($object->{FmtArgs} || 0) < $numArgs);
Packit 857059
						# Fallthrough
Packit 857059
					};
Packit 857059
					/UcIdent/	and do {
Packit 857059
						if ($val !~ /^[A-Z_][A-Z0-9_]*$/) {
Packit 857059
							error "$attr must be an uppercase identifier";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						# Fallthrough
Packit 857059
					};
Packit 857059
					/Ident/	and do {
Packit 857059
						if ($val !~ /^[A-Za-z_][A-Za-z0-9_]*$/) {
Packit 857059
							error "$attr must be an identifier";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						# Fallthrough
Packit 857059
					};
Packit 857059
					/Ident|Str/	and do {
Packit 857059
						if (defined $def->{Min} and length($val) < $def->{Min}) {
Packit 857059
							error "$attr must be at least $def->{Min} character(s)";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						elsif (defined $def->{Max} and length($val) > $def->{Max}) {
Packit 857059
							error "$attr must be no more than $def->{Max} characters";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						last;
Packit 857059
					};
Packit 857059
					/Picklist/ and do {
Packit 857059
						$val = uc $val;
Packit 857059
						if (exists $def->{Transform}) {
Packit 857059
							&{$def->{Transform}}($val);
Packit 857059
						}
Packit 857059
						if (not exists $def->{Values}{$val}) {
Packit 857059
							error "Invalid $attr";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						else {
Packit 857059
							$object->{$def->{Set}} = $def->{Values}{$val};
Packit 857059
						}
Packit 857059
						last;
Packit 857059
					};
Packit 857059
					die "Internal Error, Bad type $def->{Type}\n";
Packit 857059
				}
Packit 857059
Packit 857059
				if ($Format->{$scope}{Attributes}{$attr}{i18n}) {
Packit 857059
					if (not defined $lang) {
Packit 857059
						error "Missing language";
Packit 857059
						last LINE;
Packit 857059
					}
Packit 857059
					elsif (not exists $object->{$attr}) {
Packit 857059
						$object->{$attr} = { $lang => $val };
Packit 857059
					}
Packit 857059
					else {
Packit 857059
						if (exists $object->{$attr}{$lang}) {
Packit 857059
							error "Duplicate";
Packit 857059
							last LINE;
Packit 857059
						}
Packit 857059
						$object->{$attr}{$lang} = $val;
Packit 857059
					}
Packit 857059
				}
Packit 857059
				else {
Packit 857059
					if (defined $lang) {
Packit 857059
						error "Non-internationalized attribute $attr";
Packit 857059
						last LINE;
Packit 857059
					}
Packit 857059
					elsif (exists $object->{$attr}) {
Packit 857059
						error "Duplicate attribute $attr";
Packit 857059
						last LINE;
Packit 857059
					}
Packit 857059
					else {
Packit 857059
						$object->{$attr} = $val;
Packit 857059
						if ($attr eq "Name") {
Packit 857059
							$context = "$scope $val";
Packit 857059
						}
Packit 857059
					}
Packit 857059
				}
Packit 857059
				last;
Packit 857059
			};
Packit 857059
Packit 857059
			# section header
Packit 857059
			/^\[(\w+)\]$/		and do {
Packit 857059
				my $new_scope = ucfirst lc $1;
Packit 857059
Packit 857059
				if ($new_scope eq "Done") {
Packit 857059
					# flush
Packit 857059
					new_scope("Done");
Packit 857059
					# validate sections
Packit 857059
					foreach my $check_scope (keys %$Format) {
Packit 857059
						#print "check $check_scope: ";
Packit 857059
						if (not exists $File->{$check_scope}) {
Packit 857059
							#print "Missing ";
Packit 857059
							if ($Format->{$check_scope}{Required}) {
Packit 857059
								#print "Required\n";
Packit 857059
								error "Missing required section $check_scope";
Packit 857059
							}
Packit 857059
							elsif ($Format->{$check_scope}{Default} or
Packit 857059
								   $Format->{$check_scope}{Calculate})
Packit 857059
							{
Packit 857059
								#print "Defaulting ";
Packit 857059
								$object = $Format->{$check_scope}{Default}
Packit 857059
												? $Format->{$check_scope}{Default}
Packit 857059
												: &{$Format->{$check_scope}{Calculate}};
Packit 857059
								#print "Validating ";
Packit 857059
								$scope = $check_scope;
Packit 857059
								new_scope("Done");
Packit 857059
							}
Packit 857059
						}
Packit 857059
						#print "Done\n";
Packit 857059
					}
Packit 857059
				}
Packit 857059
				elsif ($scope eq "Done") {
Packit 857059
					# internal use
Packit 857059
					$scope = $new_scope;
Packit 857059
				}
Packit 857059
				elsif (not exists $Format->{$new_scope}) {
Packit 857059
					error "Unknown section $new_scope";
Packit 857059
				}
Packit 857059
				else {
Packit 857059
					if ($Format->{$new_scope}{Singular} and
Packit 857059
						(exists $File->{$new_scope} or $scope eq $new_scope))
Packit 857059
					{
Packit 857059
						error "Only one $new_scope section is permitted";
Packit 857059
					}
Packit 857059
					new_scope($new_scope);
Packit 857059
				}
Packit 857059
				last;
Packit 857059
			};
Packit 857059
Packit 857059
			error "Syntax Error";
Packit 857059
		}
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
{
Packit 857059
	my $f_posarg = '[1-9]\d*\$';
Packit 857059
	my $f_flags = '[ #+0\-]';
Packit 857059
	my $f_width = "(?:[1-9]\\d*|\\*(?:$f_posarg)?)";
Packit 857059
	my $f_precis = "(?:\\.(?:\\d*|\\*(?:$f_posarg)?))";
Packit 857059
	my $f_size = '[hq]|(?:ll?)';
Packit 857059
	my $f_type = '[cCdiFopsSuxXM]';
Packit 857059
Packit 857059
			#       $1         $2          $3         $4          $5         $6         $7        $8
Packit 857059
	my $fmt = "($f_posarg)?($f_flags*)($f_posarg)?($f_width)?($f_precis)?($f_posarg)?($f_size)?($f_type)";
Packit 857059
Packit 857059
	#
Packit 857059
	# Scan a string and validate printf format specifiers. Returns the number of
Packit 857059
	# arguments on success, dies with a descriptive string on error.
Packit 857059
	#
Packit 857059
	sub validate_format($) {
Packit 857059
		my $str = $_[0];
Packit 857059
		my $have_pos = 0;
Packit 857059
		my $pos_mixed = 0;
Packit 857059
		my $numargs = 0;
Packit 857059
Packit 857059
		$testMode and print "validate_format($str)\n";
Packit 857059
		while (length($str) and not $pos_mixed) {
Packit 857059
			# strip stuff before the first %
Packit 857059
			$str =~ s/^[^%]*//;
Packit 857059
Packit 857059
			if (length($str)) {
Packit 857059
				# is it a valid format?
Packit 857059
				if ($str =~ s/^(?:\%\%|\%$fmt)//o) {
Packit 857059
					my $numPos = (defined $1) + (defined $3) + (defined $6);
Packit 857059
					if ($numPos > 1) {
Packit 857059
						error "Multiple positional specifiers '", defined $1 ? $1 : $3,
Packit 857059
							  $numPos == 3 ? "', '$3'," : "'",
Packit 857059
							  " and '", defined $5 ? $5 : $3, "' in format specifier";
Packit 857059
					}
Packit 857059
					my $pos = defined $1 ? $1 : defined $3 ? $3 : $6;
Packit 857059
					my $flags = $2;
Packit 857059
					my $width = $4;
Packit 857059
					my $precis = $5;
Packit 857059
					my $size = $7;
Packit 857059
					my $type = $8;
Packit 857059
Packit 857059
					# check for repeating flags (not really a problem, but ugly)
Packit 857059
					$flags = join('', sort(split //, $flags));
Packit 857059
					$testMode and print "Flags are: '$flags'\n";
Packit 857059
					if ($flags =~ /(.)\1/) {
Packit 857059
						warning "Repeated flag '$1' in format specifier";
Packit 857059
					}
Packit 857059
Packit 857059
					# check for positional and non-positional parameters
Packit 857059
					if (defined $pos) {
Packit 857059
						my $arg = substr($pos, 0, length($pos) - 1);
Packit 857059
						$testMode and print "positional $pos, arg is $arg\n";
Packit 857059
						$numargs = $arg if ($arg > $numargs);
Packit 857059
						$have_pos = 1;
Packit 857059
					}
Packit 857059
					else {
Packit 857059
						$pos_mixed = $have_pos;
Packit 857059
						$numargs++;	# not the right place, but gets the right count
Packit 857059
					}
Packit 857059
					if (defined $width and $width =~ /^\*($f_posarg)?$/o) {
Packit 857059
						if (defined $1) {
Packit 857059
							my $arg = substr($1, 0, length($1) - 1);
Packit 857059
							$testMode and print "width $width, arg is $arg\n";
Packit 857059
							$numargs = $arg if ($arg > $numargs);
Packit 857059
							$have_pos = 1;
Packit 857059
						}
Packit 857059
						else {
Packit 857059
							$pos_mixed = $have_pos;
Packit 857059
							$numargs++;
Packit 857059
						}
Packit 857059
					}
Packit 857059
					if (defined $precis and $precis =~ /^\.\*($f_posarg)?$/o) {
Packit 857059
						if (defined $1) {
Packit 857059
							my $arg = substr($1, 0, length($1) - 1);
Packit 857059
							$testMode and print "precision $precis, arg is $arg\n";
Packit 857059
							$numargs = $arg if ($arg > $numargs);
Packit 857059
							$have_pos = 1;
Packit 857059
						}
Packit 857059
						else {
Packit 857059
							$pos_mixed = $have_pos;
Packit 857059
							$numargs++;
Packit 857059
						}
Packit 857059
					}
Packit 857059
					if ($have_pos and not defined $pos) {
Packit 857059
						$pos_mixed = 1;
Packit 857059
					}
Packit 857059
Packit 857059
					# TODO: validate size-type combos?
Packit 857059
				}
Packit 857059
				else {
Packit 857059
					error "Invalid format specifier at \"$str\"";
Packit 857059
					# strip the '%' so we can recover
Packit 857059
					$str = substr($str, 1);
Packit 857059
				}
Packit 857059
			}
Packit 857059
		}
Packit 857059
		if ($pos_mixed) {
Packit 857059
			error "Format mixes positional and non positional parameters";
Packit 857059
		}
Packit 857059
Packit 857059
		return $numargs;
Packit 857059
	}
Packit 857059
Packit 857059
	#
Packit 857059
	# Scan a string and return a list of arguments which are IFormattable objects
Packit 857059
	#
Packit 857059
	sub find_formattable($) {
Packit 857059
		my $str = $_[0];
Packit 857059
		my $nextarg = 1;
Packit 857059
		my %formattable = ();
Packit 857059
Packit 857059
		while ($str =~ /\G(?:[^\%]|\%\%)*\%$fmt/go)
Packit 857059
		{
Packit 857059
			my $pos = defined $1 ? $1 : defined $3 ? $3 : $6;
Packit 857059
			my $width = $4;
Packit 857059
			my $precis = $5;
Packit 857059
			my $type = $8;
Packit 857059
Packit 857059
			if (defined $pos) {
Packit 857059
				substr($pos, -1) = '';
Packit 857059
				$nextarg = $pos;
Packit 857059
			}
Packit 857059
			if (defined $width and $width eq '*') {
Packit 857059
				$nextarg++;
Packit 857059
			}
Packit 857059
			if (defined $precis and substr($precis, 1) eq '*') {
Packit 857059
				$nextarg++;
Packit 857059
			}
Packit 857059
			if ($type eq 'F') {
Packit 857059
				$formattable{$nextarg}++;
Packit 857059
			}
Packit 857059
			$nextarg++;
Packit 857059
		}
Packit 857059
Packit 857059
		return sort keys %formattable;
Packit 857059
	}
Packit 857059
Packit 857059
	#
Packit 857059
	# Scan a string and return a list of arguments which are pointers
Packit 857059
	#
Packit 857059
	sub find_pointer($) {
Packit 857059
		my $str = $_[0];
Packit 857059
		my $nextarg = 1;
Packit 857059
		my %pointer = ();
Packit 857059
Packit 857059
		while ($str =~ /\G(?:[^\%]|\%\%)*\%$fmt/go)
Packit 857059
		{
Packit 857059
			my $pos = defined $1 ? $1 : defined $3 ? $3 : $6;
Packit 857059
			my $width = $4;
Packit 857059
			my $precis = $5;
Packit 857059
			my $type = $8;
Packit 857059
Packit 857059
			if (defined $pos) {
Packit 857059
				substr($pos, -1) = '';
Packit 857059
				$nextarg = $pos;
Packit 857059
			}
Packit 857059
			if (defined $width and $width eq '*') {
Packit 857059
				$nextarg++;
Packit 857059
			}
Packit 857059
			if (defined $precis and substr($precis, 1) eq '*') {
Packit 857059
				$nextarg++;
Packit 857059
			}
Packit 857059
			if ($type eq 's' or $type eq 'p') {
Packit 857059
				$pointer{$nextarg}++;
Packit 857059
			}
Packit 857059
			$nextarg++;
Packit 857059
		}
Packit 857059
Packit 857059
		return sort keys %pointer;
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
#
Packit 857059
# Extract names of arguments from an argument list
Packit 857059
#
Packit 857059
sub get_names(\%) {
Packit 857059
	my $obj = $_[0];
Packit 857059
	my @list;
Packit 857059
	my %seen = ();
Packit 857059
Packit 857059
	if (not defined $obj->{Arglist}) {
Packit 857059
		return ();
Packit 857059
	}
Packit 857059
Packit 857059
	for (my $i = 1; $i <= scalar(@{$obj->{Arglist}}); $i++) {
Packit 857059
		if ($obj->{Arglist}[$i-1] =~ /^([a-zA-Z_]\w+)(?:\s*:.*)?$/) {
Packit 857059
			$list[$i-1] = $1;
Packit 857059
		}
Packit 857059
		else {
Packit 857059
			warning "No name given for $obj->{Name} argument $i, defaulting to arg$i";
Packit 857059
			$list[$i-1] = "arg$i";
Packit 857059
		}
Packit 857059
		if ($seen{$list[$i-1]}) {
Packit 857059
			error "Duplicate argument name ", $list[$i-1], " for $obj->{Name}";
Packit 857059
		}
Packit 857059
		$seen{$list[$i-1]} = 1;
Packit 857059
	}
Packit 857059
Packit 857059
	return @list;
Packit 857059
}
Packit 857059
Packit 857059
#
Packit 857059
# Find the union of two (or more) lists
Packit 857059
#
Packit 857059
sub union {
Packit 857059
	my %union = ();
Packit 857059
Packit 857059
	foreach my $i (@_) {
Packit 857059
		$union{$i}++;
Packit 857059
	}
Packit 857059
Packit 857059
	return sort keys %union;
Packit 857059
}
Packit 857059
Packit 857059
#
Packit 857059
# Main Loop
Packit 857059
#
Packit 857059
Packit 857059
#main()
Packit 857059
Packit 857059
my $cur_line = "";
Packit 857059
Packit 857059
if (scalar @ARGV != 1) {
Packit 857059
	print "Usage: buildmsgs.pl Module.msg\n";
Packit 857059
	print "\nCreates/overwrites Module_Messages.c and Module_Messages.h.\n";
Packit 857059
	exit(1);
Packit 857059
}
Packit 857059
Packit 857059
$msgFile = shift;
Packit 857059
($defModName,undef,undef) = fileparse($msgFile, '\..*');
Packit 857059
$msgFileLine = 0;
Packit 857059
my $fileBase = $defModName . "_Messages";
Packit 857059
Packit 857059
if ($msgFile eq '--test') {
Packit 857059
	$testMode = 1;
Packit 857059
	while (<>) {
Packit 857059
		my $line = $_;
Packit 857059
		chomp $line;
Packit 857059
		++$msgFileLine;
Packit 857059
		my $rslt = validate_format($line);
Packit 857059
		print "$rslt arguments\n";
Packit 857059
		my @formattable = find_formattable($line);
Packit 857059
		my @pointer = find_pointer($line);
Packit 857059
		print "IFormattable args: ", join(', ', @formattable), "\n" if (@formattable);
Packit 857059
		print "Pointer args: ", join(', ', @pointer), "\n" if (@pointer);
Packit 857059
		print "\n";
Packit 857059
	}
Packit 857059
	exit 0;
Packit 857059
}
Packit 857059
Packit 857059
my $msg_file = new FileHandle "$msgFile" or die "$msgFile: ERROR: $!\n";
Packit 857059
Packit 857059
while (<$msg_file>) {
Packit 857059
	s/((?:".*")*)\s*(?:#.*)?$/$1/;	# strip comments
Packit 857059
	s/\s*$//;	# strip trailing whitespace
Packit 857059
	if (s/^\t[ \t]*/ /) {	# continuation line
Packit 857059
		$cur_line .= $_;
Packit 857059
	}
Packit 857059
	else {
Packit 857059
		if (length($cur_line)) {
Packit 857059
			parse_line($cur_line);
Packit 857059
		}
Packit 857059
		$cur_line = $_;
Packit 857059
	}
Packit 857059
	++$msgFileLine;
Packit 857059
}
Packit 857059
Packit 857059
# handle last line
Packit 857059
if (length($cur_line)) {
Packit 857059
	parse_line($cur_line);
Packit 857059
}
Packit 857059
Packit 857059
# flush any in-progress object
Packit 857059
parse_line("[Done]");
Packit 857059
Packit 857059
close $msg_file;
Packit 857059
Packit 857059
# ensure we have a MODNAME str as the first string
Packit 857059
if (not exists $File->{String} or $File->{String}[0]{Name} ne "MODNAME") {
Packit 857059
	if (exists $File->{String}) {
Packit 857059
		for (my $i = 1; $i < scalar(@{$File->{String}}); $i++) {
Packit 857059
			if ($File->{String}[$i]{Name} eq "MODNAME") {
Packit 857059
				error "MODNAME must be the first string";
Packit 857059
			}
Packit 857059
		}
Packit 857059
	}
Packit 857059
	parse_line("[String]");
Packit 857059
	parse_line("Name=MODNAME");
Packit 857059
	parse_line("comment=first entry must be 1-6 character package name");
Packit 857059
	foreach my $lang (@languages) {
Packit 857059
		parse_line("String.$lang=\"$File->{Module}{Name}\"");
Packit 857059
	}
Packit 857059
	parse_line("[Done]");
Packit 857059
Packit 857059
	# rotate to the beginning of the list
Packit 857059
	unshift @{$File->{String}}, pop @{$File->{String}};
Packit 857059
}
Packit 857059
Packit 857059
# ensure MODNAME str is 1-6 characters
Packit 857059
foreach my $lang (@languages) {
Packit 857059
	my $str = $File->{String}[0]{String}{$lang};
Packit 857059
Packit 857059
	# value includes quotes
Packit 857059
	if (length $str < 3 or length $str > 9) {
Packit 857059
		error "MODNAME string must be 1-6 characters ($lang string $str is ",
Packit 857059
			length($str)- 2, " characters";
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
if ($errorCount) {
Packit 857059
	die "$msgFile: $warnCount warnings, $errorCount errors\n";
Packit 857059
}
Packit 857059
elsif ($warnCount) {
Packit 857059
	warn "$msgFile: $warnCount warnings\n"
Packit 857059
}
Packit 857059
Packit 857059
#
Packit 857059
# generate output
Packit 857059
#
Packit 857059
Packit 857059
my $modName = $File->{Module}{Name};
Packit 857059
my $ucModName = $File->{Module}{Ucname};
Packit 857059
my $lcModName = lcfirst $modName;
Packit 857059
my $mod = "MOD_$ucModName";
Packit 857059
Packit 857059
my $header = new FileHandle ">$fileBase.h" or die "$msgFile: ERROR: Could not open $fileBase.h for write\n";
Packit 857059
my $source = new FileHandle ">$fileBase.c" or die "$msgFile: ERROR: Could not open $fileBase.c for write\n";
Packit 857059
Packit 857059
#
Packit 857059
# Mod_Messages.h
Packit 857059
#
Packit 857059
my $oldfh = select $header;
Packit 857059
print <<"EOF";
Packit 857059
#ifndef ${ucModName}_MESSAGES_H_INCLUDED
Packit 857059
#define ${ucModName}_MESSAGES_H_INCLUDED
Packit 857059
Packit 857059
/*!
Packit 857059
 \@file    $modName/$fileBase.h
Packit 857059
 \@brief   Nationalizable Strings and Messages for $modName Package generated from $msgFile
Packit 857059
 */
Packit 857059
Packit 857059
#include "Gen_Arch.h"
Packit 857059
#include "Gen_Macros.h"
Packit 857059
#include "Log.h"
Packit 857059
Packit 857059
EOF
Packit 857059
Packit 857059
if (exists $File->{Message}) {
Packit 857059
	my $need_macros = 0;
Packit 857059
	print "/* Messages */\n";
Packit 857059
	for (my $i = 0; $i < scalar(@{$File->{Message}}); $i++) {
Packit 857059
		printf "#define %s_MSG_%-25s LOG_BUILD_MSGID(%s, %d)\n",
Packit 857059
				$ucModName, $File->{Message}->[$i]->{Name}, $mod, $i;
Packit 857059
		$need_macros = 1 if (exists $File->{Message}->[$i]->{Severity});
Packit 857059
	}
Packit 857059
	if ($need_macros) {
Packit 857059
		print "\n/* Logging Macros */\n";
Packit 857059
		for (my $i = 0; $i < scalar(@{$File->{Message}}); $i++) {
Packit 857059
			my $msg = $File->{Message}->[$i];
Packit 857059
Packit 857059
			next if (not exists $msg->{Severity}); 
Packit 857059
Packit 857059
			my $msgName = $msg->{Name};
Packit 857059
			my @args = get_names(%$msg);
Packit 857059
			my @fmt = find_formattable($msg->{Description}{$languages[0]});
Packit 857059
			my @ptr = find_pointer($msg->{Description}{$languages[0]});
Packit 857059
			if (defined $msg->{Response}) {
Packit 857059
				@fmt = union(@fmt, find_formattable($msg->{Response}{$languages[0]}));
Packit 857059
				@ptr = union(@ptr, find_pointer($msg->{Response}{$languages[0]}));
Packit 857059
			}
Packit 857059
			if (defined $msg->{Correction}) {
Packit 857059
				@fmt = union(@fmt, find_formattable($msg->{Correction}{$languages[0]}));
Packit 857059
				@ptr = union(@ptr, find_pointer($msg->{Correction}{$languages[0]}));
Packit 857059
			}
Packit 857059
			my @rvArgs = @args;
Packit 857059
			foreach my $arg (@fmt) {
Packit 857059
				$rvArgs[$arg-1] = 'LOG_FORMATTABLE('. $rvArgs[$arg-1] . ')';
Packit 857059
			}
Packit 857059
			foreach my $arg (@ptr) {
Packit 857059
				$rvArgs[$arg-1] = 'LOG_PTR('. $rvArgs[$arg-1] . ')';
Packit 857059
			}
Packit 857059
			for (my $arg = scalar(@rvArgs); $arg < 6; $arg++) {
Packit 857059
				$rvArgs[$arg] = 0;
Packit 857059
			}
Packit 857059
			#printf STDOUT "%s: %d, %d\n", $msgName, scalar(@args), scalar(@rvArgs);
Packit 857059
Packit 857059
			printf "/* %s_MSG_%s", $ucModName, $msgName;
Packit 857059
			if (exists $msg->{Comment}) {
Packit 857059
				print ": $msg->{Comment}";
Packit 857059
			}
Packit 857059
			if (exists $msg->{Arglist}) {
Packit 857059
				print "\n * Arguments: \n";
Packit 857059
				for (my $i = 0; $i < scalar(@{$msg->{Arglist}}); $i++) {
Packit 857059
					printf " *\t%s\n", $msg->{Arglist}[$i];
Packit 857059
				}
Packit 857059
			}
Packit 857059
			print " */\n";
Packit 857059
			printf "#define %s_%s_%s(%s)\\\n\tLOG_%s(MOD_%s, %s_MSG_%s, %s)\n",
Packit 857059
					$ucModName, $msg->{Class}, $msgName, join(', ', @args),
Packit 857059
					$msg->{Severity}, $ucModName, $ucModName, $msgName, join(', ', @rvArgs);
Packit 857059
		}
Packit 857059
	}
Packit 857059
}
Packit 857059
Packit 857059
print "\n/* Constant Strings for use as substitutionals in Messages */\n";
Packit 857059
my $need_macros = 0;
Packit 857059
for (my $i = 0; $i < scalar(@{$File->{String}}); $i++) {
Packit 857059
	printf "#define %s_STR_%-25s LOG_BUILD_STRID(%s, %d)\n",
Packit 857059
			$ucModName, $File->{String}->[$i]->{Name}, $mod, $i;
Packit 857059
	$need_macros = 1 if (exists $File->{String}->[$i]->{Arglist});
Packit 857059
}
Packit 857059
if ($need_macros) {
Packit 857059
	print "\n/* String Formatting Macros */\n";
Packit 857059
	for (my $i = 0; $i < scalar(@{$File->{String}}); $i++) {
Packit 857059
		my $str = $File->{String}->[$i];
Packit 857059
Packit 857059
		next if (not exists $str->{Arglist});
Packit 857059
Packit 857059
		my @args = get_names(%$str);
Packit 857059
		my @fmt = find_formattable($str->{String}{$languages[0]});
Packit 857059
		my @ptr = find_pointer($str->{String}{$languages[0]});
Packit 857059
		my @rvArgs = @args;
Packit 857059
		foreach my $arg (@fmt) {
Packit 857059
			$rvArgs[$arg-1] = 'LOG_FORMATTABLE('. $rvArgs[$arg-1] . ')';
Packit 857059
		}
Packit 857059
		foreach my $arg (@ptr) {
Packit 857059
			$rvArgs[$arg-1] = 'LOG_PTR('. $rvArgs[$arg-1] . ')';
Packit 857059
		}
Packit 857059
		for (my $arg = scalar(@rvArgs); $arg < 6; $arg++) {
Packit 857059
			$rvArgs[$arg] = 0;
Packit 857059
		}
Packit 857059
		printf "/* %s_STR_%s", $ucModName, $str->{Name};
Packit 857059
		if (exists $str->{Comment}) {
Packit 857059
			print ": $str->{Comment}";
Packit 857059
		}
Packit 857059
		if (exists $str->{Arglist}) {
Packit 857059
			print "\n * Arguments: \n";
Packit 857059
			for (my $i = 0; $i < scalar(@{$str->{Arglist}}); $i++) {
Packit 857059
				printf " *\t%s\n", $str->{Arglist}[$i];
Packit 857059
			}
Packit 857059
		}
Packit 857059
		print " */\n";
Packit 857059
		printf "#define %s_FMT_%s(buffer, %s)\\\n\t", $ucModName, $str->{Name}, join(', ', @args);
Packit 857059
		printf "LOG_FORMATBUF(buffer, Log_GetString(%s_STR_%s, (buffer).GetLanguage()), %s)\n",
Packit 857059
				$ucModName, $str->{Name}, join(', ', @rvArgs);
Packit 857059
	}
Packit 857059
}
Packit 857059
print "\n";
Packit 857059
Packit 857059
print <<"EOF";
Packit 857059
GEN_EXTERNC(extern void ${modName}_AddMessages();)
Packit 857059
Packit 857059
#endif /* ${ucModName}_MESSAGES_H_INCLUDED */
Packit 857059
EOF
Packit 857059
Packit 857059
#
Packit 857059
# Mod_Messages.c
Packit 857059
#
Packit 857059
select $source;
Packit 857059
print <<"EOF";
Packit 857059
/*!
Packit 857059
 \@file    $modName/$fileBase.c
Packit 857059
 \@brief   Nationalizable Strings and Messages for $modName Package generated from $msgFile
Packit 857059
 */
Packit 857059
Packit 857059
#include "$fileBase.h"
Packit 857059
Packit 857059
EOF
Packit 857059
Packit 857059
Packit 857059
Packit 857059
Packit 857059
Packit 857059
if (exists $File->{Message}) {   
Packit 857059
   # Loop through and add all the trap fun ptr prototypes at the top
Packit 857059
   foreach my $msg (@{$File->{Message}}) {
Packit 857059
           if(not $msg->{Trapfunc} eq "LOG_TRAP_NONE"){
Packit 857059
             printf "extern Log_TrapFunc_t %s;\n", $msg->{Trapfunc};
Packit 857059
           }
Packit 857059
   }
Packit 857059
   print "\n\n";
Packit 857059
Packit 857059
Packit 857059
   print <<"EOF";
Packit 857059
Packit 857059
/*!
Packit 857059
Module specific message table, referenced by Log_MessageId_t.
Packit 857059
Packit 857059
The entries in the table must provide equivalent argument usage for
Packit 857059
all languages.  Argument usage in format strings is used to determine
Packit 857059
which arguments may need to be freed
Packit 857059
*/
Packit 857059
Packit 857059
static Log_MessageEntry_t ${lcModName}_messageTable[] =
Packit 857059
{
Packit 857059
EOF
Packit 857059
	foreach my $msg (@{$File->{Message}}) {
Packit 857059
		printf "\t{\t%s_MSG_%s,%s\n", $ucModName, $msg->{Name},
Packit 857059
									  exists $msg->{Comment} ? "\t/* $msg->{'comment'} */" : '';
Packit 857059
		printf "\t\t%d,\t/* argument number which holds unit number, 0 -> none */\n", $msg->{Unitarg};
Packit 857059
		printf "\t\t%s,\t/* trap func associated with message */\n", $msg->{Trapfunc};
Packit 857059
		print "\t\t/* FUTURE - Binary Data */\n";
Packit 857059
		if (exists $msg->{Arglist}) {
Packit 857059
			my $args = $msg->{Arglist};
Packit 857059
			print "\t\t/* Arguments: \n";
Packit 857059
			for (my $i = 0; $i < scalar(@$args); $i++) {
Packit 857059
				printf "\t\t *\targ%d -> %s\n", $i + 1, $args->[$i];
Packit 857059
			}
Packit 857059
			print "\t\t */\n";
Packit 857059
		}
Packit 857059
		else {
Packit 857059
			print "\t\t/* Arguments: None */\n";
Packit 857059
		}
Packit 857059
		print "\t\t{ /* Language Specific Entries */\n";
Packit 857059
		foreach my $lang (@languages) {
Packit 857059
			print  "\t\t\t{ /* LOG_LANG_$lang */\n";
Packit 857059
			printf "\t\t\t\t/* description */ %s,\n", $msg->{Description}->{$lang};
Packit 857059
			printf "\t\t\t\t/* response */    %s,\n", $msg->{Response}->{$lang};
Packit 857059
			printf "\t\t\t\t/* correction */  %s,\n", $msg->{Correction}->{$lang};
Packit 857059
			print "\t\t\t},\n";
Packit 857059
		}
Packit 857059
		print "\t\t},\n\t},\n";
Packit 857059
	}
Packit 857059
	print "};\n\n";
Packit 857059
}
Packit 857059
Packit 857059
print <<"EOF";
Packit 857059
Packit 857059
/*!
Packit 857059
Module specific string table, referenced by Log_StringId_t.
Packit 857059
*/
Packit 857059
Packit 857059
static Log_StringEntry_t ${lcModName}_stringTable[] =
Packit 857059
{
Packit 857059
EOF
Packit 857059
foreach my $str (@{$File->{String}}) {
Packit 857059
	printf "\t{\t%s_STR_%s,%s\n", $ucModName, $str->{Name},
Packit 857059
								  exists $str->{Comment} ? "\t/* $str->{Comment} */" : '';
Packit 857059
	if (defined $str->{Arglist}) {
Packit 857059
		my $args = $str->{Arglist};
Packit 857059
		print "\t\t/* Arguments: \n";
Packit 857059
		for (my $i = 0; $i < scalar(@$args); $i++) {
Packit 857059
			printf "\t\t *\targ%d -> %s\n", $i + 1, $args->[$i];
Packit 857059
		}
Packit 857059
		print "\t\t */\n";
Packit 857059
	}
Packit 857059
	my $lch = '{';
Packit 857059
	foreach my $lang (@languages) {
Packit 857059
		printf  "\t\t$lch /* LOG_LANG_$lang */ %s,\n", $str->{String}->{$lang};
Packit 857059
		$lch = ' ';
Packit 857059
	}
Packit 857059
	print "\t\t},\n\t},\n";
Packit 857059
}
Packit 857059
print "};\n\n";
Packit 857059
Packit 857059
print <<'EOF';
Packit 857059
/*!
Packit 857059
Add String table to logging subsystem's tables.
Packit 857059
Packit 857059
This must be run early in the boot to initialize tables prior to
Packit 857059
any logging functions being available.
Packit 857059
Packit 857059
@return None
Packit 857059
Packit 857059
@heading Concurrency Considerations
Packit 857059
    Must be run once, early in boot
Packit 857059
Packit 857059
@heading Special Cases and Error Handling
Packit 857059
	None
Packit 857059
Packit 857059
@see Log_AddStringTable
Packit 857059
*/
Packit 857059
Packit 857059
EOF
Packit 857059
Packit 857059
printf "void\n%s_AddMessages()\n{\n", $modName;
Packit 857059
	printf "\tLog_AddStringTable(MOD_%s, %s_stringTable,\n".
Packit 857059
		   "\t\t\t\t\t\tGEN_NUMENTRIES(%s_stringTable));\n",
Packit 857059
		   $ucModName, $lcModName, $lcModName;
Packit 857059
if (exists $File->{Message}) {
Packit 857059
	printf "\tLog_AddMessageTable(MOD_%s, %s_messageTable,\n".
Packit 857059
		   "\t\t\t\t\t\tGEN_NUMENTRIES(%s_messageTable));\n",
Packit 857059
		   $ucModName, $lcModName, $lcModName;
Packit 857059
}
Packit 857059
print "}\n";
Packit 857059
Packit 857059
select $oldfh;
Packit 857059
Packit 857059
close $header;
Packit 857059
close $source;