Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
d6ccd9c
Lots of architectural changes
ElijahSwiftIBM Jul 8, 2026
0220c46
some cmake changes?
ElijahSwiftIBM Jul 10, 2026
78c4928
some cmake changes 2
ElijahSwiftIBM Jul 10, 2026
2fc2a39
some cmake changes 3
ElijahSwiftIBM Jul 10, 2026
1785e77
some cmake changes 4
ElijahSwiftIBM Jul 10, 2026
d8d70d1
some cmake changes 5
ElijahSwiftIBM Jul 10, 2026
f12837e
some cmake changes 6
ElijahSwiftIBM Jul 10, 2026
d51043e
some cmake changes 7
ElijahSwiftIBM Jul 10, 2026
847c48b
some cmake changes 8
ElijahSwiftIBM Jul 10, 2026
6ac4993
some cmake changes 9
ElijahSwiftIBM Jul 10, 2026
643554e
some cmake changes 10
ElijahSwiftIBM Jul 10, 2026
e6cfad2
tweaks just trying to get it working 1
ElijahSwiftIBM Aug 5, 2026
b720c43
tweaks just trying to get it working 2
ElijahSwiftIBM Aug 5, 2026
3aee0bc
tweaks just trying to get it working 2
ElijahSwiftIBM Aug 5, 2026
03cb835
tweaks just trying to get it working 3
ElijahSwiftIBM Aug 5, 2026
d5376aa
tweaks just trying to get it working 4
ElijahSwiftIBM Aug 5, 2026
df4d884
tweaks just trying to get it working 5
ElijahSwiftIBM Aug 5, 2026
3c69550
tweaks just trying to get it working 6
ElijahSwiftIBM Aug 5, 2026
a18c163
tweaks just trying to get it working 6
ElijahSwiftIBM Aug 5, 2026
5f1a430
tweaks just trying to get it working 7
ElijahSwiftIBM Aug 5, 2026
8fc2bfa
tweaks just trying to get it working 8
ElijahSwiftIBM Aug 5, 2026
58878ab
tweaks just trying to get it working 9
ElijahSwiftIBM Aug 5, 2026
ae0666f
tweaks just trying to get it working 10
ElijahSwiftIBM Aug 5, 2026
229f849
tweaks just trying to get it working 11?
ElijahSwiftIBM Aug 5, 2026
4069b00
tweaks just trying to get it working 12
ElijahSwiftIBM Aug 5, 2026
00b024a
tweaks just trying to get it working 13
ElijahSwiftIBM Aug 5, 2026
9a3e412
tweaks just trying to get it working 14
ElijahSwiftIBM Aug 5, 2026
12d84b5
tweaks just trying to get it working 15
ElijahSwiftIBM Aug 5, 2026
79b688b
tweaks just trying to get it working 16
ElijahSwiftIBM Aug 5, 2026
548fbc4
tweaks just trying to get it working 17
ElijahSwiftIBM Aug 5, 2026
d903616
tweaks just trying to get it working 18
ElijahSwiftIBM Aug 5, 2026
6b4d382
tweaks just trying to get it working 19?
ElijahSwiftIBM Aug 5, 2026
438a249
tweaks just trying to get it working 20
ElijahSwiftIBM Aug 7, 2026
bcf0091
tweaks just trying to get it working 21
ElijahSwiftIBM Aug 7, 2026
09a6baa
tweaks just trying to get it working 22
ElijahSwiftIBM Aug 7, 2026
3b7adeb
tweaks just trying to get it working 23
ElijahSwiftIBM Aug 10, 2026
95ce073
tweaks just trying to get it working 24
ElijahSwiftIBM Aug 11, 2026
3fac375
tweaks just trying to get it working 25
ElijahSwiftIBM Aug 11, 2026
092b86f
tweaks just trying to get it working 26
ElijahSwiftIBM Aug 18, 2026
da1673b
tweaks just trying to get it working 27
ElijahSwiftIBM Aug 18, 2026
791f3a6
tweaks just trying to get it working 28
ElijahSwiftIBM Aug 18, 2026
0869662
tweaks just trying to get it working 29
ElijahSwiftIBM Aug 18, 2026
345107e
tweaks just trying to get it working 30
ElijahSwiftIBM Aug 18, 2026
e2117f7
tweaks just trying to get it working 31
ElijahSwiftIBM Aug 18, 2026
4f1f551
tweaks just trying to get it working 32
ElijahSwiftIBM Aug 18, 2026
1f24f52
tweaks just trying to get it working 33
ElijahSwiftIBM Aug 18, 2026
e05abf7
tweaks just trying to get it working 34
ElijahSwiftIBM Aug 18, 2026
b50f64f
tweaks just trying to get it working 35
ElijahSwiftIBM Aug 18, 2026
e57e983
tweaks just trying to get it working 36
ElijahSwiftIBM Aug 19, 2026
e463219
tweaks just trying to get it working 37
ElijahSwiftIBM Aug 19, 2026
f2d6bdd
tweaks just trying to get it working 38
ElijahSwiftIBM Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ artifacts
dist
cbxp-*
*egg-info/
cbxp/mappings/*.hpp
cbxp/schemas/*.hpp

# CMake
CMakeLists.txt.user
Expand Down
60 changes: 58 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ file(
GLOB CBXP_SRC_LIB
"cbxp/*.cpp"
"cbxp/control_blocks/*.cpp"
"externals/json-schema-validator/*.cpp"
)

file(
Expand All @@ -63,18 +64,73 @@ file(
# ============================================================================
# Build '/lib/libcbxp.a'
# ============================================================================
# ============================================================================
# Generate schema header from cbxp/schemas/control_block_v1.json
# ============================================================================
set(CBXP_SCHEMAS_GENERATED_DIR "${CMAKE_BINARY_DIR}/cbxp/schemas")
file(MAKE_DIRECTORY "${CBXP_SCHEMAS_GENERATED_DIR}")

file(READ "${CMAKE_CURRENT_SOURCE_DIR}/cbxp/schemas/control_block_v1.json" CBXP_SCHEMA_JSON)

file(WRITE "${CBXP_SCHEMAS_GENERATED_DIR}/control_block_v1.hpp"
"#ifndef CBXP_SCHEMA_CONTROL_BLOCK_V1_JSON_HPP\n\
#define CBXP_SCHEMA_CONTROL_BLOCK_V1_JSON_HPP\n\
\n\
#define CBXP_SCHEMA_JSON R\"JSON(${CBXP_SCHEMA_JSON})JSON\"\n\
\n\
#endif // CBXP_SCHEMA_CONTROL_BLOCK_V1_JSON_HPP\n"
)

# ============================================================================
# Generate mapping headers from JSON files in cbxp/mappings/
# ============================================================================
set(CBXP_MAPPINGS_GENERATED_DIR "${CMAKE_BINARY_DIR}/cbxp/mappings")
file(MAKE_DIRECTORY "${CBXP_MAPPINGS_GENERATED_DIR}")

file(GLOB CBXP_MAPPING_JSON_FILES "${CMAKE_CURRENT_SOURCE_DIR}/cbxp/mappings/*.json")

set(CBXP_MAPPING_FORCED_INCLUDES "")

foreach(MAPPING_JSON_FILE ${CBXP_MAPPING_JSON_FILES})
get_filename_component(MAPPING_NAME "${MAPPING_JSON_FILE}" NAME_WE)
string(TOUPPER "${MAPPING_NAME}" MAPPING_NAME_UPPER)

file(READ "${MAPPING_JSON_FILE}" MAPPING_JSON)

set(MAPPING_GUARD "${MAPPING_NAME_UPPER}_JSON_HPP")
set(MAPPING_MACRO "${MAPPING_NAME_UPPER}_JSON")
set(MAPPING_HEADER_PATH "${CBXP_MAPPINGS_GENERATED_DIR}/${MAPPING_NAME}.hpp")

file(WRITE "${MAPPING_HEADER_PATH}"
"#ifndef ${MAPPING_GUARD}\n\
#define ${MAPPING_GUARD}\n\
\n\
#define ${MAPPING_MACRO} R\"JSON(${MAPPING_JSON})JSON\"\n\
\n\
#endif // ${MAPPING_GUARD}\n"
)

list(APPEND CBXP_MAPPING_FORCED_INCLUDES "--include=${MAPPING_HEADER_PATH}")
endforeach()

add_library(libcbxp STATIC ${CBXP_SRC_LIB})
set_target_properties(libcbxp PROPERTIES OUTPUT_NAME "cbxp")

target_include_directories(
libcbxp PUBLIC
cbxp
cbxp/control_blocks
externals
externals/json
externals/json-schema-validator
/usr/include/zos
)

target_compile_options(libcbxp PUBLIC ${COMPILE_OPTIONS})
target_compile_options(
libcbxp PUBLIC
${COMPILE_OPTIONS}
"--include=${CBXP_SCHEMAS_GENERATED_DIR}/control_block_v1.hpp"
${CBXP_MAPPING_FORCED_INCLUDES}
)
target_link_options(libcbxp PUBLIC ${LINK_OPTIONS})

# ============================================================================
Expand Down
25 changes: 16 additions & 9 deletions cbxp/cbxp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <nlohmann/json.hpp>

#include "control_block_error.hpp"
#include "control_block_explorer.hpp"
#include "logger.hpp"

Expand Down Expand Up @@ -31,11 +32,14 @@ cbxp_result_t* cbxp_extract(const char* control_block_name,
CBXP::Logger::getInstance().debugAllocate(p_cbxp_result, 64,
sizeof(cbxp_result_t));

CBXP::ControlBlockExplorer explorer =
CBXP::ControlBlockExplorer(p_cbxp_result);

explorer.extractControlBlock(control_block_name_string,
includes_string_string, filters_string_string);
try {
CBXP::ControlBlockExplorer explorer =
CBXP::ControlBlockExplorer(p_cbxp_result);
explorer.extractControlBlock(control_block_name_string,
includes_string_string, filters_string_string);
} catch (const CBXP::CBXPError& e) {
p_cbxp_result->return_code = e.getErrorCode();
}

return p_cbxp_result;
}
Expand All @@ -57,10 +61,13 @@ cbxp_result_t* cbxp_format(const char* control_block_name,
CBXP::Logger::getInstance().debugAllocate(p_cbxp_result, 64,
sizeof(cbxp_result_t));

CBXP::ControlBlockExplorer explorer =
CBXP::ControlBlockExplorer(p_cbxp_result);

explorer.formatControlBlock(control_block_name_string, data, data_length);
try {
CBXP::ControlBlockExplorer explorer =
CBXP::ControlBlockExplorer(p_cbxp_result);
explorer.formatControlBlock(control_block_name_string, data, data_length);
} catch (const CBXP::CBXPError& e) {
p_cbxp_result->return_code = e.getErrorCode();
}

return p_cbxp_result;
}
Expand Down
17 changes: 17 additions & 0 deletions cbxp/cbxp_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef __CBXP_TYPES_H_
#define __CBXP_TYPES_H_

#include <string>
#include <vector>

namespace CBXP {

typedef struct {
std::vector<std::string> include_patterns;
std::vector<std::string> filters;
bool skip_buffer_length_check;
} cbxp_options_t;

} // namespace CBXP

#endif
12 changes: 11 additions & 1 deletion cbxp/cli/command_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,18 @@ void CommandProcessor::run() {
case CBXP::Error::DataTooSmall:
std::cerr << ERROR_DATA_TOO_SMALL_ << control_block_name_ << std::endl;
throw CLIExitFailure();
case CBXP::Error::BadCbxpPath:
std::cerr << ERROR_BAD_CBXP_ENV_PATH_ << std::endl;
throw CLIExitFailure();
case CBXP::Error::CantReachBlock:
std::cerr << ERROR_CANT_REACH_BLOCK_ << std::endl;
throw CLIExitFailure();
case CBXP::Error::BadJsonFile:
std::cerr << ERROR_JSON_FILE_ << std::endl;
throw CLIExitFailure();
default:
std::cerr << ERROR_UNKNOWN_ERROR_ << control_block_name_ << std::endl;
std::cerr << ERROR_UNKNOWN_ERROR_ << " " << control_block_name_
<< std::endl;
throw CLIExitFailure();
}
throw CLIExitSuccess();
Expand Down
4 changes: 4 additions & 0 deletions cbxp/cli/command_processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class CommandProcessor {
const std::string ERROR_CONTROL_BLOCK_EXPECTED_ =
"Positional argument <control block> expected";
const std::string ERROR_UNKNOWN_ERROR_ = "An unknown error occurred";
const std::string ERROR_BAD_CBXP_ENV_PATH_ =
"Error with your CBXPPATH environment variable";
const std::string ERROR_CANT_REACH_BLOCK_ = "Cannot reach control block";
const std::string ERROR_JSON_FILE_ = "Could not parse a JSON file";
// Format
const std::string ERROR_OFFSET_MUST_BE_A_POSITIVE_INTEGER_ =
"Offset must be a positive integer";
Expand Down
20 changes: 19 additions & 1 deletion cbxp/control_block_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ enum Error {
BadInclude = 2,
BadFilter = 3,
DataTooSmall = 4,
NullDataPtr = 5
NullDataPtr = 5,
BadCbxpPath = 6,
BadJsonFile = 7,
CantReachBlock = 8,
};

class CBXPError : public std::exception {
Expand Down Expand Up @@ -39,6 +42,21 @@ class DataLengthError : public CBXPError {
DataLengthError() : CBXPError(Error::DataTooSmall) {}
};

class CbxpPathError : public CBXPError {
public:
CbxpPathError() : CBXPError(Error::BadCbxpPath) {}
};

class CbxpJsonError : public CBXPError {
public:
CbxpJsonError() : CBXPError(Error::BadJsonFile) {}
};

class CbxpReachBlockError : public CBXPError {
public:
CbxpReachBlockError() : CBXPError(Error::CantReachBlock) {}
};

} // namespace CBXP

#endif
148 changes: 115 additions & 33 deletions cbxp/control_block_explorer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,121 @@

#include <algorithm>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>

#include "cbxp.h"
#include "control_block_error.hpp"
#include "control_blocks/ascb.hpp"
#include "control_blocks/assb.hpp"
#include "control_blocks/asvt.hpp"
#include "control_blocks/control_block.hpp"
#include "control_blocks/cvt.hpp"
#include "control_blocks/ecvt.hpp"
#include "control_blocks/ldax.hpp"
#include "control_blocks/oucb.hpp"
#include "control_blocks/psa.hpp"
#include "logger.hpp"

namespace CBXP {

bool ControlBlockExplorer::control_blocks_init_failed_ = false;

std::unordered_map<std::string, ControlBlock>
ControlBlockExplorer::control_blocks_ =
ControlBlockExplorer::buildControlBlockMap();

std::unordered_map<std::string, ControlBlock>
ControlBlockExplorer::loadCustomControlBlocks(
const nlohmann::json_schema::json_validator& cbxp_schema_validator,
std::filesystem::path path) {
std::unordered_map<std::string, ControlBlock> new_maps = {};
if (!std::filesystem::exists(path) || !std::filesystem::is_directory(path)) {
throw CbxpPathError();
}
for (const auto& file : std::filesystem::directory_iterator(path)) {
if (file.path().extension() != ".json") {
continue;
}
std::string file_name = file.path().stem().string();
std::ifstream ifs(file.path());
nlohmann::json json_data = nlohmann::json::parse(ifs);
Logger::getInstance().debug("Adding '" + file_name +
"' control block from '" +
file.path().string() + "'.");
new_maps.emplace(file_name, ControlBlock(cbxp_schema_validator, json_data));
}
return new_maps;
}

std::string ControlBlockExplorer::mapToString(
const std::unordered_map<std::string, ControlBlock>& map) {
std::string map_as_string = "";
if (map.empty()) {
return map_as_string;
}
map_as_string = "[";

bool first_entry = true;
for (const auto& [key, value] : map) {
if (!first_entry) {
map_as_string += ", ";
} else {
first_entry = false;
}
map_as_string += key;
}

map_as_string += "]";
return map_as_string;
}

std::unordered_map<std::string, ControlBlock>
ControlBlockExplorer::buildControlBlockMap() {
nlohmann::json_schema::json_validator cbxp_schema_validator(
nlohmann::json::parse(CBXP_SCHEMA_JSON));
std::unordered_map<std::string, ControlBlock> control_blocks;
// Load known control blocks
try {
control_blocks = {
{ "psa",
ControlBlock(cbxp_schema_validator, nlohmann::json::parse(PSA_JSON))},
{ "cvt",
ControlBlock(cbxp_schema_validator, nlohmann::json::parse(CVT_JSON))},
{"ecvt",
ControlBlock(cbxp_schema_validator, nlohmann::json::parse(ECVT_JSON))},
{"asvt",
ControlBlock(cbxp_schema_validator, nlohmann::json::parse(ASVT_JSON))},
{"ascb",
ControlBlock(cbxp_schema_validator, nlohmann::json::parse(ASCB_JSON))},
{"assb",
ControlBlock(cbxp_schema_validator, nlohmann::json::parse(ASSB_JSON))},
//{"oucb", ControlBlock(cbxp_schema_validator, OUCB_JSON)},
//{"ldax", ControlBlock(cbxp_schema_validator, LDAX_JSON)},
};
} catch (const std::exception& e) {
control_blocks_init_failed_ = true;
return {};
}

// Load custom control blocks
std::string env_p(std::getenv("CBXPPATH"));
if (env_p.empty()) {
return control_blocks;
}
// Logic for loading custom control block mappings, overwriting any that were
// already loaded with custom mappings as well.
std::filesystem::path cbxp_path(env_p);
for (const auto& path : cbxp_path) {
std::unordered_map<std::string, ControlBlock> custom_control_blocks =
ControlBlockExplorer::loadCustomControlBlocks(cbxp_schema_validator,
path);
if (!custom_control_blocks.empty()) {
Logger::getInstance().debug(
"Added the following custom control blocks from path '" +
path.string() +
"': " + ControlBlockExplorer::mapToString(custom_control_blocks));
custom_control_blocks.insert(control_blocks.begin(),
control_blocks.end());
}
}
return control_blocks;
}

std::vector<std::string> ControlBlockExplorer::createOptionsList(
const std::string& comma_separated_string) {
if (comma_separated_string == "") {
Expand Down Expand Up @@ -92,31 +189,16 @@ void ControlBlockExplorer::processControlBlock(
nlohmann::json control_block_json = {};

try {
if (control_block_name == "psa") {
control_block_json =
PSA(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "cvt") {
control_block_json =
CVT(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "ecvt") {
control_block_json =
ECVT(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "ascb") {
control_block_json =
ASCB(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "asvt") {
control_block_json =
ASVT(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "assb") {
control_block_json =
ASSB(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "oucb") {
control_block_json =
OUCB(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "ldax") {
control_block_json =
LDAX(cbxp_options_).get(p_control_block_, control_block_data_length_);

if (control_blocks_init_failed_) {
Logger::getInstance().debug(
"Static initialization of JSON mappings failed.");
throw CbxpJsonError();
}
if (control_blocks_.find(control_block_name) != control_blocks_.end()) {
ExplorerOptionsMap explorer_options =
ExplorerOptionsMap(cbxp_options_, control_block_name, control_blocks_,
p_control_block_, control_block_data_length_);
control_block_json = explorer_options.getControlBlockData();
} else {
throw ControlBlockError();
}
Expand Down
Loading
Loading