diff --git a/build/lib/pgBackRestBuild/Error/Build.pm b/build/lib/pgBackRestBuild/Error/Build.pm deleted file mode 100644 index e60d3c565..000000000 --- a/build/lib/pgBackRestBuild/Error/Build.pm +++ /dev/null @@ -1,136 +0,0 @@ -#################################################################################################################################### -# Auto-Generate Error Mappings -#################################################################################################################################### -package pgBackRestBuild::Error::Build; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); -use English '-no_match_vars'; - -use Exporter qw(import); - our @EXPORT = qw(); - -use pgBackRestDoc::Common::Log; - -use pgBackRestBuild::Build::Common; -use pgBackRestBuild::Error::Data; - -#################################################################################################################################### -# Constants -#################################################################################################################################### -use constant BLDLCL_FILE_DEFINE => 'error'; - -use constant BLDLCL_DATA_ERROR => '01-dataError'; -use constant BLDLCL_DATA_ERROR_ARRAY => '01-dataErrorArray'; - -#################################################################################################################################### -# Definitions for constants and data to build -#################################################################################################################################### -my $strSummary = 'Error Type Definition'; - -my $rhBuild = -{ - &BLD_FILE => - { - &BLDLCL_FILE_DEFINE => - { - &BLD_SUMMARY => $strSummary, - - &BLD_DECLARE => - { - &BLDLCL_DATA_ERROR => - { - &BLD_SUMMARY => 'Error type declarations', - }, - }, - - &BLD_DATA => - { - &BLDLCL_DATA_ERROR => - { - &BLD_SUMMARY => 'Error type definitions', - }, - - &BLDLCL_DATA_ERROR_ARRAY => - { - &BLD_SUMMARY => 'Error type array', - }, - }, - }, - }, -}; - -#################################################################################################################################### -# Build configuration constants and data -#################################################################################################################################### -sub buildError -{ - # Build error list - #------------------------------------------------------------------------------------------------------------------------------- - my $rhErrorDefine = errorDefine(); - - # Order by id for the list that is id ordered - my $rhErrorId = {}; - - foreach my $strType (sort(keys(%{$rhErrorDefine}))) - { - my $iCode = $rhErrorDefine->{$strType}; - - if (defined($rhErrorId->{$iCode})) - { - confess &log(ERROR, "error code ${iCode} is by '" . $rhErrorId->{$iCode} . "' and '${strType}'"); - } - - $rhErrorId->{$iCode} = $strType; - } - - # Output errors - my $strBuildSource; - - foreach my $iCode (sort({sprintf("%03d", $a) cmp sprintf("%03d", $b)} keys(%{$rhErrorId}))) - { - my $strType = $rhErrorId->{$iCode}; - - $strBuildSource .= - "ERROR_DECLARE(" . bldEnum("", $strType, true) . "Error);\n"; - } - - $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DECLARE}{&BLDLCL_DATA_ERROR}{&BLD_SOURCE} = $strBuildSource; - - # Output error definition data - $strBuildSource = undef; - - foreach my $iCode (sort({sprintf("%03d", $a) cmp sprintf("%03d", $b)} keys(%{$rhErrorId}))) - { - my $strType = $rhErrorId->{$iCode}; - - $strBuildSource .= - "ERROR_DEFINE(" . (' ' x (3 - length($iCode))) . "${iCode}, " . bldEnum("", $strType, true) . "Error, RuntimeError);\n"; - } - - $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_ERROR}{&BLD_SOURCE} = $strBuildSource; - - # Output error array - $strBuildSource = - "static const ErrorType *errorTypeList[] =\n" . - "{\n"; - - foreach my $iCode (sort({sprintf("%03d", $a) cmp sprintf("%03d", $b)} keys(%{$rhErrorId}))) - { - $strBuildSource .= - " &" . bldEnum("", $rhErrorId->{$iCode}, true) . "Error,\n"; - } - - $strBuildSource .= - " NULL,\n" . - "};"; - - $rhBuild->{&BLD_FILE}{&BLDLCL_FILE_DEFINE}{&BLD_DATA}{&BLDLCL_DATA_ERROR_ARRAY}{&BLD_SOURCE} = $strBuildSource; - - return $rhBuild; -} - -push @EXPORT, qw(buildError); - -1; diff --git a/build/lib/pgBackRestBuild/Error/Data.pm b/build/lib/pgBackRestBuild/Error/Data.pm deleted file mode 100644 index c869f5957..000000000 --- a/build/lib/pgBackRestBuild/Error/Data.pm +++ /dev/null @@ -1,52 +0,0 @@ -#################################################################################################################################### -# Error Definition Data -#################################################################################################################################### -package pgBackRestBuild::Error::Data; - -use strict; -use warnings FATAL => qw(all); -use Carp qw(confess); - -use Exporter qw(import); - our @EXPORT = qw(); -use Storable qw(dclone); - -#################################################################################################################################### -# Error min and max values -#################################################################################################################################### -use constant ERRDEF_MIN => 25; - push @EXPORT, qw(ERRDEF_MIN); -use constant ERRDEF_MAX => 125; - push @EXPORT, qw(ERRDEF_MAX); - -#################################################################################################################################### -# Error definition data -#################################################################################################################################### -my $rhErrorDefine; - -#################################################################################################################################### -# Load error definition from YAML -#################################################################################################################################### -sub errorDefineLoad -{ - my $strErrorYaml = shift; - - require YAML::XS; - YAML::XS->import(qw(Load)); - - $rhErrorDefine = Load($strErrorYaml); -} - -push @EXPORT, qw(errorDefineLoad); - -#################################################################################################################################### -# Get error definition -#################################################################################################################################### -sub errorDefine -{ - return dclone($rhErrorDefine); -} - -push @EXPORT, qw(errorDefine); - -1; diff --git a/src/Makefile.in b/src/Makefile.in index cb6e46530..f5190e3ca 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -221,6 +221,22 @@ build-config: $(OBJS_BUILD_CONFIG) build/config/config.yaml config/config.auto.h $(CC) -o build-config $(OBJS_BUILD_CONFIG) $(LDFLAGS) $(LIBS) $(LIBS_BUILD) ./build-config $(VPATH) +#################################################################################################################################### +# Compile and link error generator +#################################################################################################################################### +SRCS_BUILD_ERROR = \ + build/common/render.c \ + build/common/yaml.c \ + build/error/main.c \ + build/error/parse.c \ + build/error/render.c + +OBJS_BUILD_ERROR = $(patsubst %.c,$(BUILDDIR)/%.o,$(SRCS_BUILD) $(SRCS_BUILD_ERROR)) + +build-error: $(OBJS_BUILD_ERROR) build/error/error.yaml + $(CC) -o build-error $(OBJS_BUILD_ERROR) $(LDFLAGS) $(LIBS) $(LIBS_BUILD) + ./build-error $(VPATH) + #################################################################################################################################### # Installation. DESTDIR can be used to modify the install location. #################################################################################################################################### diff --git a/build/error.yaml b/src/build/error/error.yaml similarity index 100% rename from build/error.yaml rename to src/build/error/error.yaml diff --git a/src/build/error/main.c b/src/build/error/main.c new file mode 100644 index 000000000..3f5b98668 --- /dev/null +++ b/src/build/error/main.c @@ -0,0 +1,42 @@ +/*********************************************************************************************************************************** +Auto-Generate Errors +***********************************************************************************************************************************/ +#include + +#include "common/log.h" +#include "storage/posix/storage.h" + +#include "build/error/parse.h" +#include "build/error/render.h" + +int +main(int argListSize, const char *argList[]) +{ + // Check parameters + CHECK(argListSize <= 2); + + // Initialize logging + logInit(logLevelWarn, logLevelError, logLevelOff, false, 0, 1, false); + + // If the path was specified + const String *pathRepo; + + if (argListSize >= 2) + { + pathRepo = strPath(STR(argList[1])); + } + // Else use current working directory + else + { + char currentWorkDir[1024]; + THROW_ON_SYS_ERROR(getcwd(currentWorkDir, sizeof(currentWorkDir)) == NULL, FormatError, "unable to get cwd"); + + pathRepo = strPath(STR(currentWorkDir)); + } + + // Render error + const Storage *const storageRepo = storagePosixNewP(pathRepo, .write = true); + bldErrRender(storageRepo, bldErrParse(storageRepo)); + + return 0; +} diff --git a/src/build/error/parse.c b/src/build/error/parse.c new file mode 100644 index 000000000..ea7e36526 --- /dev/null +++ b/src/build/error/parse.c @@ -0,0 +1,95 @@ +/*********************************************************************************************************************************** +Parse Error Yaml +***********************************************************************************************************************************/ +#include "build.auto.h" + +#include + +#include "common/log.h" +#include "common/macro.h" +#include "common/type/convert.h" +#include "storage/posix/storage.h" + +#include "build/common/yaml.h" +#include "build/error/parse.h" + +/*********************************************************************************************************************************** +Error min/max codes +***********************************************************************************************************************************/ +#define ERROR_CODE_MIN 25 +#define ERROR_CODE_MAX 125 + +/*********************************************************************************************************************************** +Parse error list +***********************************************************************************************************************************/ +typedef struct BldErrErrorRaw +{ + const String *const name; // See BldErrError for comments + unsigned int code; +} BldErrErrorRaw; + +static List * +bldErrParseErrorList(Yaml *const yaml) +{ + List *const result = lstNewP(sizeof(BldErrError), .comparator = lstComparatorStr); + + MEM_CONTEXT_TEMP_BEGIN() + { + yamlEventNextCheck(yaml, yamlEventTypeMapBegin); + + YamlEvent err = yamlEventNext(yaml); + + do + { + yamlEventCheck(err, yamlEventTypeScalar); + + BldErrErrorRaw errRaw = + { + .name = err.value, + }; + + // Parse error code and check that it is valid + YamlEvent errVal = yamlEventNextCheck(yaml, yamlEventTypeScalar); + errRaw.code = cvtZToUInt(strZ(errVal.value)); + + if (errRaw.code < ERROR_CODE_MIN || errRaw.code > ERROR_CODE_MAX) + { + THROW_FMT( + FormatError, "error '%s' code must be >= " STRINGIFY(ERROR_CODE_MIN) " and <= " STRINGIFY(ERROR_CODE_MAX), + strZ(errRaw.name)); + } + + // Add to list + MEM_CONTEXT_BEGIN(lstMemContext(result)) + { + lstAdd( + result, + &(BldErrError) + { + .name = strDup(errRaw.name), + .code = errRaw.code, + }); + } + MEM_CONTEXT_END(); + + err = yamlEventNext(yaml); + } + while (err.type != yamlEventTypeMapEnd); + } + MEM_CONTEXT_TEMP_END(); + + return result; +} + +/**********************************************************************************************************************************/ +BldErr +bldErrParse(const Storage *const storageRepo) +{ + // Initialize yaml + Yaml *const yaml = yamlNew(storageGetP(storageNewReadP(storageRepo, STRDEF("src/build/error/error.yaml")))); + + // Parse error + const List *const errList = bldErrParseErrorList(yaml); + + return (BldErr){.errList = errList}; +} diff --git a/src/build/error/parse.h b/src/build/error/parse.h new file mode 100644 index 000000000..f708fc51e --- /dev/null +++ b/src/build/error/parse.h @@ -0,0 +1,29 @@ +/*********************************************************************************************************************************** +Parse Error Yaml +***********************************************************************************************************************************/ +#ifndef BUILD_ERROR_PARSE_H +#define BUILD_ERROR_PARSE_H + +#include "common/type/string.h" + +/*********************************************************************************************************************************** +Types +***********************************************************************************************************************************/ +typedef struct BldErrError +{ + const String *const name; // Name + const unsigned int code; // Code +} BldErrError; + +typedef struct BldErr +{ + const List *const errList; // Command list +} BldErr; + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +// Parse error.yaml +BldErr bldErrParse(const Storage *const storageRepo); + +#endif diff --git a/src/build/error/render.c b/src/build/error/render.c new file mode 100644 index 000000000..667a61108 --- /dev/null +++ b/src/build/error/render.c @@ -0,0 +1,138 @@ +/*********************************************************************************************************************************** +Render Error Data +***********************************************************************************************************************************/ +#include "build.auto.h" + +#include + +#include "common/log.h" +#include "storage/posix/storage.h" + +#include "build/common/render.h" +#include "build/error/render.h" + +/*********************************************************************************************************************************** +Build error name from a string +***********************************************************************************************************************************/ +static String * +bldErrName(const String *const value) +{ + String *const result = strNew(); + const char *const valuePtr = strZ(value); + + bool upper = true; + + for (unsigned int valueIdx = 0; valueIdx < strSize(value); valueIdx++) + { + strCatChr(result, upper ? (char)toupper(valuePtr[valueIdx]) : valuePtr[valueIdx]); + upper = false; + + if (valuePtr[valueIdx + 1] == '-') + { + upper = true; + valueIdx++; + } + } + + strCatZ(result, "Error"); + + return result; +} + +/*********************************************************************************************************************************** +Render error.auto.h +***********************************************************************************************************************************/ +#define ERROR_MODULE "error" +#define ERROR_AUTO_COMMENT "Error Type Definition" + +static void +bldErrRenderErrorAutoH(const Storage *const storageRepo, const BldErr bldErr) +{ + String *error = strNewFmt( + "%s" + "#ifndef COMMON_ERROR_AUTO_H\n" + "#define COMMON_ERROR_AUTO_H\n", + strZ(bldHeader(ERROR_MODULE, ERROR_AUTO_COMMENT))); + + // Error declarations + // ----------------------------------------------------------------------------------------------------------------------------- + strCatZ( + error, + "\n" + COMMENT_BLOCK_BEGIN "\n" + "Error type declarations\n" + COMMENT_BLOCK_END "\n"); + + for (unsigned int errIdx = 0; errIdx < lstSize(bldErr.errList); errIdx++) + { + const BldErrError *const err = lstGet(bldErr.errList, errIdx); + + strCatFmt(error, "ERROR_DECLARE(%s);\n", strZ(bldErrName(err->name))); + } + + // End and save + strCatZ( + error, + "\n" + "#endif\n"); + + bldPut(storageRepo, "src/common/error.auto.h", BUFSTR(error)); +} + +/*********************************************************************************************************************************** +Render error.auto.c +***********************************************************************************************************************************/ +static void +bldErrRenderErrorAutoC(const Storage *const storageRepo, const BldErr bldErr) +{ + String *error = bldHeader(ERROR_MODULE, ERROR_AUTO_COMMENT); + + // Error type definitions + // ----------------------------------------------------------------------------------------------------------------------------- + strCatZ( + error, + "\n" + COMMENT_BLOCK_BEGIN "\n" + "Error type definitions\n" + COMMENT_BLOCK_END "\n"); + + for (unsigned int errIdx = 0; errIdx < lstSize(bldErr.errList); errIdx++) + { + const BldErrError *const err = lstGet(bldErr.errList, errIdx); + + strCatFmt(error, "ERROR_DEFINE(%3u, %s, RuntimeError);\n", err->code, strZ(bldErrName(err->name))); + } + + // Error type array + // ----------------------------------------------------------------------------------------------------------------------------- + strCatZ( + error, + "\n" + COMMENT_BLOCK_BEGIN "\n" + "Error type array\n" + COMMENT_BLOCK_END "\n" + "static const ErrorType *errorTypeList[] =\n" + "{\n"); + + for (unsigned int errIdx = 0; errIdx < lstSize(bldErr.errList); errIdx++) + { + const BldErrError *const err = lstGet(bldErr.errList, errIdx); + + strCatFmt(error, " &%s,\n", strZ(bldErrName(err->name))); + } + + strCatZ( + error, + " NULL,\n" + "};\n"); + + bldPut(storageRepo, "src/common/error.auto.c", BUFSTR(error)); +} + +/**********************************************************************************************************************************/ +void +bldErrRender(const Storage *const storageRepo, const BldErr bldErr) +{ + bldErrRenderErrorAutoH(storageRepo, bldErr); + bldErrRenderErrorAutoC(storageRepo, bldErr); +} diff --git a/src/build/error/render.h b/src/build/error/render.h new file mode 100644 index 000000000..0abde055e --- /dev/null +++ b/src/build/error/render.h @@ -0,0 +1,15 @@ +/*********************************************************************************************************************************** +Render Error Data +***********************************************************************************************************************************/ +#ifndef BUILD_ERROR_RENDER_H +#define BUILD_ERROR_RENDER_H + +#include "build/error/parse.h" + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +// Render auto-generated error files +void bldErrRender(const Storage *const storageRepo, const BldErr bldErr); + +#endif diff --git a/src/common/error.auto.c b/src/common/error.auto.c index 64fcadf32..de316eca3 100644 --- a/src/common/error.auto.c +++ b/src/common/error.auto.c @@ -1,7 +1,7 @@ /*********************************************************************************************************************************** Error Type Definition -Automatically generated by Build.pm -- do not modify directly. +Automatically generated by 'make build-error' -- do not modify directly. ***********************************************************************************************************************************/ /*********************************************************************************************************************************** diff --git a/src/common/error.auto.h b/src/common/error.auto.h index a05229b17..22cca64ae 100644 --- a/src/common/error.auto.h +++ b/src/common/error.auto.h @@ -1,7 +1,7 @@ /*********************************************************************************************************************************** Error Type Definition -Automatically generated by Build.pm -- do not modify directly. +Automatically generated by 'make build-error' -- do not modify directly. ***********************************************************************************************************************************/ #ifndef COMMON_ERROR_AUTO_H #define COMMON_ERROR_AUTO_H diff --git a/test/define.yaml b/test/define.yaml index a182d6ac9..2aae6e4de 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -623,6 +623,14 @@ unit: - build/config/parse - build/config/render + # ---------------------------------------------------------------------------------------------------------------------------- + - name: error + total: 1 + + coverage: + - build/error/parse + - build/error/render + # ******************************************************************************************************************************** - name: info diff --git a/test/src/module/build/errorTest.c b/test/src/module/build/errorTest.c new file mode 100644 index 000000000..455d30034 --- /dev/null +++ b/test/src/module/build/errorTest.c @@ -0,0 +1,101 @@ +/*********************************************************************************************************************************** +Test Build Error +***********************************************************************************************************************************/ +#include "common/harnessStorage.h" + +/*********************************************************************************************************************************** +Test Run +***********************************************************************************************************************************/ +void +testRun(void) +{ + FUNCTION_HARNESS_VOID(); + + // Create default storage object for testing + Storage *storageTest = storagePosixNewP(TEST_PATH_STR, .write = true); + + // ***************************************************************************************************************************** + if (testBegin("bldErrParse() and bldErrRender()")) + { + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("parse errors"); + + HRN_STORAGE_PUT_Z( + storageTest, "src/build/error/error.yaml", + "assert: 24\n"); + + TEST_ERROR(bldErrParse(storageTest), FormatError, "error 'assert' code must be >= 25 and <= 125"); + + HRN_STORAGE_PUT_Z( + storageTest, "src/build/error/error.yaml", + "assert: 126\n"); + + TEST_ERROR(bldErrParse(storageTest), FormatError, "error 'assert' code must be >= 25 and <= 125"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("parse and render error"); + + HRN_STORAGE_PUT_Z( + storageTest, "src/build/error/error.yaml", + "assert: 25\n" + "option-invalid: 31\n" + "runtime: 122\n"); + + TEST_RESULT_VOID(bldErrRender(storageTest, bldErrParse(storageTest)), "parse and render"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("check error.auto.h"); + + TEST_STORAGE_GET( + storageTest, + "src/common/error.auto.h", + COMMENT_BLOCK_BEGIN "\n" + "Error Type Definition\n" + "\n" + "Automatically generated by 'make build-error' -- do not modify directly.\n" + COMMENT_BLOCK_END "\n" + "#ifndef COMMON_ERROR_AUTO_H\n" + "#define COMMON_ERROR_AUTO_H\n" + "\n" + COMMENT_BLOCK_BEGIN "\n" + "Error type declarations\n" + COMMENT_BLOCK_END "\n" + "ERROR_DECLARE(AssertError);\n" + "ERROR_DECLARE(OptionInvalidError);\n" + "ERROR_DECLARE(RuntimeError);\n" + "\n" + "#endif\n"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("check error.auto.c"); + + TEST_STORAGE_GET( + storageTest, + "src/common/error.auto.c", + COMMENT_BLOCK_BEGIN "\n" + "Error Type Definition\n" + "\n" + "Automatically generated by 'make build-error' -- do not modify directly.\n" + COMMENT_BLOCK_END "\n" + "\n" + COMMENT_BLOCK_BEGIN "\n" + "Error type definitions\n" + COMMENT_BLOCK_END "\n" + "ERROR_DEFINE( 25, AssertError, RuntimeError);\n" + "ERROR_DEFINE( 31, OptionInvalidError, RuntimeError);\n" + "ERROR_DEFINE(122, RuntimeError, RuntimeError);\n" + "\n" + COMMENT_BLOCK_BEGIN "\n" + "Error type array\n" + COMMENT_BLOCK_END "\n" + "static const ErrorType *errorTypeList[] =\n" + "{\n" + " &AssertError,\n" + " &OptionInvalidError,\n" + " &RuntimeError,\n" + " NULL,\n" + "};\n"); + } + + FUNCTION_HARNESS_RETURN_VOID(); +} diff --git a/test/test.pl b/test/test.pl index 9d114e5d5..af60de64e 100755 --- a/test/test.pl +++ b/test/test.pl @@ -37,8 +37,6 @@ use pgBackRestDoc::ProjectInfo; use pgBackRestBuild::Build; use pgBackRestBuild::Build::Common; use pgBackRestBuild::Config::BuildHelp; -use pgBackRestBuild::Error::Build; -use pgBackRestBuild::Error::Data; use pgBackRestTest::Common::BuildTest; use pgBackRestTest::Common::CodeCountTest; @@ -538,8 +536,6 @@ eval # Auto-generate C files #----------------------------------------------------------------------------------------------------------------------- - errorDefineLoad(${$oStorageBackRest->get("build/error.yaml")}); - my $rhBuild = { 'configHelp' => @@ -547,12 +543,6 @@ eval &BLD_DATA => buildConfigHelp(), &BLD_PATH => 'command/help', }, - - 'error' => - { - &BLD_DATA => buildError(), - &BLD_PATH => 'common', - }, }; my @stryBuilt = buildAll("${strBackRestBase}/src", $rhBuild); @@ -568,8 +558,8 @@ eval &log(INFO, " autogenerated C code: " . (@stryBuilt ? join(', ', @stryBuilt) : 'no changes')); - # Build configuration - executeTest("make -C ${strBuildPath} build-config"); + # Build code + executeTest("make -C ${strBuildPath} build-config build-error"); if ($bGenOnly) {