#
# Command & Conquer Generals Zero Hourâ„¢
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
sub ShowWarning;
sub ShowError;
$noxScript = shift || 'C:\Nox\Game\nox.str';
$outFile = shift;
open(STR, $noxScript) || die "Can't open Nox string file: $!\n";
if ($outFile)
{
open(STDOUT, ">$outFile") || die "Can't open output file: $!\n";
}
select((select(STDOUT), $| = 1)[0]);
$state = 0;
$line = 0;
$strcount = 0;
$strMaxCount = 32;
$lastFileName = "";
$lastFileNameLine = 0;
$ignoreErrors = 0;
$errCount = 0;
%labels = ();
while ()
{
$strline = $_;
$line++;
$strline =~ s/\/\/.*//g;
$strline =~ s/^\s*//g;
$strline =~ s/\s*$//g;
if (! ($strline eq ""))
{
if ($state == 0)
{
if (! ($strline =~ /^[^\"][^ :]*:[^ :]*[^\"]$/))
{
ShowError($line, $strline, "Expecting 'file:name'\n");
}
else
{
if (defined ($labels{$strline}))
{
ShowWarning($line, $strline, "Duplicate label at line $labels{$strline}\n");
}
$labels{$strline} = $line;
$lastFileName = $strline;
$lastFileNameLine = $line;
$strcount = 0;
$ignoreErrors = 0;
$state = 1;
}
}
elsif ($state == 1)
{
if (++$strcount >= $strMaxCount)
{
ShowError($line, $strline, "Too many strings ($strcount) - suspected missing END from section $lastFileName on line $lastFileNameLine\n");
}
elsif ($strline =~ /^END$/i)
{
$state = 0;
}
elsif ($strline =~ /\/n/i)
{
ShowWarning($line, $strline, "'/n'? This should probably be '\\n' instead\n");
}
elsif ($strline =~ /^\"[^\"]*[^\"]$/)
{
$state = 2;
}
else
{
$strline =~ s/\"\s*={0,1}\s*[a-zA-Z0-9_\.]*[^\"]$/\"/i;
if (! ($strline =~ /^\".*\"$/))
{
if ($strline =~ /^[^\"][^ :]*:[^ :]*[^\"]$/)
{
ShowError($line, $strline, "Missing quote - suspected missing END from section $lastFileName on line $lastFileNameLine\n");
}
else
{
ShowError($line, $strline, "Missing quote\n");
}
}
}
}
elsif ($state == 2)
{
$strline =~ s/\"\s*={0,1}\s*[a-zA-Z0-9_\.]*[^\"]$/\"/i;
if (++$strcount >= $strMaxCount)
{
ShowError($line, $strline, "Too many strings ($strcount) - suspected missing END from section $lastFileName on line $lastFileNameLine\n");
}
elsif ($strline =~ /\/n/i)
{
ShowWarning($line, $strline, "'/n'? This should probably be '\\n' instead\n");
}
elsif ($strline =~ /^[^\"].*\"$/)
{
$state = 1;
}
elsif (! ($strline =~ /^[^\"].*[^\"]$/))
{
ShowError($line, $strline, "Extra quote character found at start of line\n");
}
elsif ($strline =~ /^END$/i)
{
ShowWarning($line, $strline, "Suspiciously placed 'END'. Maybe missing an end-quote from previous section\n");
}
}
}
}
if ($state != 0)
{
ShowError($line, $strline, "Missing END\n");
}
print STDOUT "$line lines processed\n";
close(STR);
if ($errCount == 0)
{
open(RESULT, ">strcheck.err") || die "Can't open output file: $!\n";
print RESULT "OK";
close (RESULT);
}
exit($errCount);
sub ShowWarning
{
my ($errLine, $errString, $errDesc) = @_;
if (length($errString) > 32)
{
$errString = substr($errString, 0, 32) . "...";
}
if ($ignoreErrors == 0)
{
print STDOUT "$noxScript($errLine) : warning: '$errString' : $errDesc";
}
$state = 0;
$ignoreErrors = 1;
}
sub ShowError
{
my ($errLine, $errString, $errDesc) = @_;
if (length($errString) > 32)
{
$errString = substr($errString, 0, 32) . "...";
}
if ($ignoreErrors == 0)
{
print STDOUT "$noxScript($errLine) : error: '$errString' : $errDesc";
$errCount++;
}
$state = 0;
$ignoreErrors = 1;
}