Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 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
2317658
getting things working 39
ElijahSwiftIBM Aug 31, 2026
ea5cf8b
getting things working 40
ElijahSwiftIBM Aug 31, 2026
8700472
getting things working 41
ElijahSwiftIBM Aug 31, 2026
da8ebdf
getting things working 42
ElijahSwiftIBM Aug 31, 2026
faffbd1
getting things working 43
ElijahSwiftIBM Aug 31, 2026
1180768
getting things working 44
ElijahSwiftIBM Aug 31, 2026
d4584da
getting things working 45
ElijahSwiftIBM Aug 31, 2026
6db2cbc
getting things working 46
ElijahSwiftIBM Sep 1, 2026
f00318b
getting things working 49
ElijahSwiftIBM Sep 1, 2026
8cea094
getting things working 50
ElijahSwiftIBM Sep 1, 2026
aa69c07
getting things working 51?
ElijahSwiftIBM Sep 14, 2026
9630a0d
getting things working 52?
ElijahSwiftIBM Sep 14, 2026
ba88342
adding back schema validation?
ElijahSwiftIBM Sep 16, 2026
03402fc
adding back schema validation - change to validation code
ElijahSwiftIBM Sep 16, 2026
02b8e33
adding back schema validation - change to validation code 2
ElijahSwiftIBM Sep 16, 2026
3809f49
taking away schema validation
ElijahSwiftIBM Sep 16, 2026
8a48f1d
adding schema validation back again?
ElijahSwiftIBM Sep 16, 2026
71ec8d7
adding schema validation back again - with changes
ElijahSwiftIBM Sep 16, 2026
42b452e
trying to get it working all over again 1
ElijahSwiftIBM Sep 16, 2026
123f24e
changing the json schema stuff again
ElijahSwiftIBM Sep 17, 2026
9c4b814
taking a crack at fixing ascb loop
ElijahSwiftIBM Sep 17, 2026
2fb6496
taking a crack at fixing ascb loop 2
ElijahSwiftIBM Sep 17, 2026
541d15c
taking a crack at fixing ascb loop 3
ElijahSwiftIBM Sep 17, 2026
5ffe57d
taking a crack at fixing ascb loop 4
ElijahSwiftIBM Sep 17, 2026
30d54a1
taking a crack at fixing ascb loop
ElijahSwiftIBM Sep 17, 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
152 changes: 119 additions & 33 deletions cbxp/control_block_explorer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,126 @@

#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 {

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;
}

const std::unordered_map<std::string, ControlBlock>&
ControlBlockExplorer::getControlBlocks() {
nlohmann::json_schema::json_validator cbxp_schema_validator;
cbxp_schema_validator.set_root_schema(
nlohmann::json::parse(CBXP_SCHEMA_JSON));

// Magic static: initialized on first call, after main() and the logger are
// ready, so any parse/construction errors are visible in debug output.
static std::unordered_map<std::string, ControlBlock> control_blocks = [&]() {
std::unordered_map<std::string, ControlBlock> map;
try {
map = {
{ "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) {
Logger::getInstance().debug("Initialization of JSON mappings failed: " +
std::string(e.what()));
return map;
}

// Load custom control blocks
const char* cbxp_path_env = std::getenv("CBXPPATH");
if (cbxp_path_env == nullptr) {
return map;
}
std::string env_p(cbxp_path_env);
if (env_p.empty()) {
return map;
}
// 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(map.begin(), map.end());
}
}
return map;
}();

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 +194,15 @@ 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_);

const auto& control_blocks = ControlBlockExplorer::getControlBlocks();
if (control_blocks.empty()) {
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