// cxxStreamProbe.cpp - exercise the C++ stream + format + path surface // (Phase 5.4). Probes the cout-replacement pattern: // // 1. etl::string_stream< "USR:BIN" check (1/0) // $02501A = pathNormalize("USR::BIN::..::LIB") => "USR:LIB" check (1/0) // $02501C = pathSplit("USR:BIN:LS") => parent="USR:BIN" + leaf="LS" (1/0) // $02501E = pathJoin rejects 65-char component (1 = correctly rejected) // $025020 = pathNormalize rejects 9-deep path (1 = correctly rejected) // $025000 = 0xC0DE reached end-of-main (sentinel for runInGno --check) #include #include #include #include "etl/chrono.h" #include "etl/string.h" #include "etl/string_stream.h" #include "etl/string_view.h" #include "etl/to_string.h" #ifdef CXX_STREAM_PROBE_WITH_FORMAT #include "etl/format.h" #endif static uint16_t streq(const char *a, const char *b) { while (*a && *b) { if (*a != *b) { return 0; } a++; b++; } return (uint16_t)((*a == 0 && *b == 0) ? 1 : 0); } int main(void) { *(volatile uint16_t *)0x025010UL = 0xBEEF; // Compile-time contract: clock-rep stays i32 (etl_profile.h override). // Avoids i64 chrono libcalls in stream + format demos. static_assert(sizeof(etl::chrono::steady_clock::duration::rep) == 4, "etl::chrono::steady_clock::rep must be i32 -- check " "ETL_CHRONO_STEADY_CLOCK_DURATION in etl_profile.h"); *(volatile uint16_t *)0x025012UL = 1; // ---- (1) etl::string_stream << int ------------------------------ // Flattened layout (no nested {}-scopes) — the bracketed-scope form // tripped a W65816 Wide32->2xi16 lowering bug on three nested // etl::string<32> stack allocations. Sequential single-string use // works fine and is the documented cout-replacement idiom. { etl::string<32> streamBuf; etl::string_stream ss(streamBuf); ss << "x=" << 42; { etl::string<32> tmp; etl::string_stream ssTmp(tmp); ssTmp << "y=" << 7; { etl::string<32> third; etl::string_stream ss3(third); ss3 << "z=" << 3; *(volatile uint16_t *)0x025014UL = streq(ss3.str().c_str(), "z=3"); } } } // ---- (2) etl::format_to(buf, "{}", 42) -------------------------- #ifdef CXX_STREAM_PROBE_WITH_FORMAT etl::string<32> formatBuf; etl::format_to(formatBuf, "{}", 42); *(volatile uint16_t *)0x025016UL = streq(formatBuf.c_str(), "42"); #else // Sentinel: format probe gated off in single-bank flavor. See // docs/GAP_CLOSURE_PLAN.md Phase 5.4 step 5 (size spike >10 KB // delta -- explicit downgrade to layer2-opt-in). *(volatile uint16_t *)0x025016UL = 1; #endif // ---- (3a) pathJoin ----------------------------------------------- char joinOut[64]; bool joinOk = iigs::path::pathJoin("USR", "BIN", joinOut, sizeof(joinOut)); *(volatile uint16_t *)0x025018UL = (uint16_t)((joinOk && streq(joinOut, "USR:BIN")) ? 1 : 0); // ---- (3b) pathNormalize collapsing & .. --------------------------- char normOut[64]; bool normOk = iigs::path::pathNormalize("USR::BIN::..::LIB", normOut, sizeof(normOut)); *(volatile uint16_t *)0x02501AUL = (uint16_t)((normOk && streq(normOut, "USR:LIB")) ? 1 : 0); // ---- (3c) pathSplit ----------------------------------------------- char splitParent[64]; char splitLeaf[64]; bool splitOk = iigs::path::pathSplit("USR:BIN:LS", splitParent, sizeof(splitParent), splitLeaf, sizeof(splitLeaf)); *(volatile uint16_t *)0x02501CUL = (uint16_t)((splitOk && streq(splitParent, "USR:BIN") && streq(splitLeaf, "LS")) ? 1 : 0); // ---- (3d) 65-char component rejection ----------------------------- char bigName[80]; for (uint16_t i = 0; i < 65; i++) { bigName[i] = 'A'; } bigName[65] = 0; char bigOut[128]; bool bigRejected = !iigs::path::pathJoin("USR", bigName, bigOut, sizeof(bigOut)); *(volatile uint16_t *)0x02501EUL = (uint16_t)(bigRejected ? 1 : 0); // ---- (3e) 9-deep path rejection ----------------------------------- char deepOut[128]; bool deepRejected = !iigs::path::pathNormalize( "A:B:C:D:E:F:G:H:I", deepOut, sizeof(deepOut)); *(volatile uint16_t *)0x025020UL = (uint16_t)(deepRejected ? 1 : 0); *(volatile uint16_t *)0x025000UL = 0xC0DE; return 0; }