import createLinuxCncInterpModule from "../../../build/wasm/core/linuxcnc_interp.js"; function allocCString(mod, value) { const bytes = mod.lengthBytesUTF8(value) + 1; const ptr = mod._malloc(bytes); mod.stringToUTF8(value, ptr, bytes); return ptr; } function ensureParentPath(mod, path) { const parts = path.split("/").filter(Boolean); let current = ""; for (const part of parts.slice(0, -1)) { current += `/${part}`; try { mod.FS.mkdir(current); } catch { // Directory already exists. } } } function copyResultString(mod, resultPtr, functionName) { if (!resultPtr) { throw new Error(`${functionName} returned null`); } return mod.UTF8ToString(resultPtr); } function callStringResult(mod, functionName, ...values) { const ptrs = values.map((value) => allocCString(mod, value)); let resultPtr = 0; try { resultPtr = mod[`_${functionName}`](...ptrs); return copyResultString(mod, resultPtr, functionName); } finally { if (resultPtr) { mod._lcinterp_free_string(resultPtr); } for (const ptr of ptrs) { mod._free(ptr); } } } export async function createLinuxCncInterpSdk(moduleOptions = {}) { const mod = await createLinuxCncInterpModule(moduleOptions); return { module: mod, writeTextFile(path, text) { ensureParentPath(mod, path); mod.FS.writeFile(path, text, { encoding: "utf8" }); }, readTextFile(path) { return mod.FS.readFile(path, { encoding: "utf8" }); }, runSimConfigProgram({ iniPath, programPath, files = [], executionMode = "fileWithIni", }) { for (const file of files) { ensureParentPath(mod, file.path); mod.FS.writeFile(file.path, file.text, { encoding: "utf8" }); if (file.executable) { mod.FS.chmod(file.path, 0o755); } } if (executionMode === "fiveAxisRemap") { return callStringResult( mod, "lcinterp_run_fiveaxis_remap_file", programPath, iniPath, ); } if (executionMode === "fileWithIni") { return callStringResult(mod, "lcinterp_run_file_with_ini", programPath, iniPath); } throw new Error(`unsupported sim config execution mode: ${executionMode}`); }, runProgram(programText) { return callStringResult(mod, "lcinterp_run_program", programText); }, runProgramWithIni(programText, iniPath) { return callStringResult(mod, "lcinterp_run_program_with_ini", programText, iniPath); }, runFile(path) { return callStringResult(mod, "lcinterp_run_file", path); }, runFileWithIni(path, iniPath) { return callStringResult(mod, "lcinterp_run_file_with_ini", path, iniPath); }, runFileWithIniContinueOnError(path, iniPath) { return callStringResult( mod, "lcinterp_run_file_with_ini_continue_on_error", path, iniPath, ); }, runFiveAxisRemapFile(path, iniPath) { return callStringResult(mod, "lcinterp_run_fiveaxis_remap_file", path, iniPath); }, runRemapFile(path, iniPath) { return callStringResult(mod, "lcinterp_run_remap_file", path, iniPath); }, runRemapFileContinueOnError(path, iniPath) { return callStringResult(mod, "lcinterp_run_remap_file_continue_on_error", path, iniPath); }, runRemapIoMdiSequence(iniPath) { return callStringResult(mod, "lcinterp_run_remap_io_mdi_sequence", iniPath); }, restoreParameters(path) { return callStringResult(mod, "lcinterp_restore_parameters", path); }, saveParameters(path, values) { const assignments = Object.entries(values) .map(([parameter, value]) => `${parameter} ${value}`) .join("\n"); return callStringResult(mod, "lcinterp_save_parameters", path, assignments); }, loadToolTable(path, options = {}) { const functionName = options.randomToolChanger ? "lcinterp_load_tool_table_random" : "lcinterp_load_tool_table"; return callStringResult(mod, functionName, path); }, saveToolTable(path) { return callStringResult(mod, "lcinterp_save_tool_table", path); }, probeInitAndSynch() { return callStringResult(mod, "lcinterp_probe_init_and_synch"); }, probeIndexer() { return callStringResult(mod, "lcinterp_probe_indexer"); }, probeNamedParameters(iniPath) { return callStringResult(mod, "lcinterp_probe_named_parameters", iniPath); }, }; }