@henols/c64-re-tools 1.1.0 → 2.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +154 -37
- package/distribution/package.ts +21 -0
- package/distribution/plugin.ts +122 -0
- package/package.json +34 -40
- package/skills/c64-assembler/SKILL.md +76 -0
- package/skills/c64-assembler/scripts/assemble.ts +110 -0
- package/skills/c64-assembler/scripts/compare.ts +84 -0
- package/skills/c64-basic/SKILL.md +66 -0
- package/skills/c64-basic/scripts/basic.ts +46 -0
- package/skills/c64-disk/SKILL.md +93 -0
- package/skills/c64-disk/scripts/containers.ts +124 -0
- package/skills/c64-disk/scripts/disk.ts +120 -0
- package/skills/c64-emulator/SKILL.md +134 -0
- package/skills/c64-knowledge/SKILL.md +166 -0
- package/skills/c64-knowledge/scripts/knowledge.ts +492 -0
- package/skills/c64-memory-map/SKILL.md +79 -0
- package/skills/c64-memory-map/scripts/memmap.ts +92 -0
- package/skills/c64-provenance/SKILL.md +110 -0
- package/skills/c64-provenance/scripts/compare.ts +152 -0
- package/skills/c64-provenance/scripts/provenance.ts +334 -0
- package/skills/c64-provenance/scripts/runtime.ts +191 -0
- package/skills/c64-provenance/scripts/separate.ts +140 -0
- package/skills/c64-reverse-engineering/SKILL.md +144 -0
- package/skills/c64-source/SKILL.md +126 -0
- package/skills/c64-source/scripts/generate.ts +490 -0
- package/skills/c64-source/scripts/loader.ts +571 -0
- package/skills/c64-source/scripts/opcodes.ts +61 -0
- package/skills/c64-source/scripts/source.ts +595 -0
- package/skills/c64-static-analysis/SKILL.md +119 -0
- package/skills/c64-static-analysis/scripts/analyze.ts +275 -0
- package/skills/c64-static-analysis/scripts/coverage.ts +78 -0
- package/skills/c64-static-analysis/scripts/findings.ts +75 -0
- package/skills/c64-static-analysis/scripts/idioms.ts +149 -0
- package/skills/c64-static-analysis/scripts/instructions.ts +105 -0
- package/skills/c64-testing/SKILL.md +103 -0
- package/skills/c64-testing/references/scenario-format.md +116 -0
- package/skills/c64-testing/scripts/checklist.ts +51 -0
- package/skills/c64-testing/scripts/run.ts +189 -0
- package/skills/c64-testing/scripts/scenario.ts +493 -0
- package/skills/c64-testing/scripts/test.ts +65 -0
- package/skills/c64-unpacker/SKILL.md +135 -0
- package/skills/c64-unpacker/scripts/evidence.ts +207 -0
- package/skills/c64-unpacker/scripts/loads.ts +209 -0
- package/skills/c64-unpacker/scripts/machine.ts +80 -0
- package/skills/c64-unpacker/scripts/stages.ts +130 -0
- package/skills/c64-unpacker/scripts/unpack.ts +683 -0
- package/src/c64.ts +411 -0
- package/src/cli/ap-sdk.ts +44 -0
- package/src/cli/cleanup.ts +194 -0
- package/src/cli/main.ts +125 -0
- package/src/cli/status.ts +61 -0
- package/src/host/main.ts +134 -0
- package/src/host/server.ts +392 -0
- package/src/host/tools/c1541.ts +284 -0
- package/src/host/tools/index.ts +35 -0
- package/src/host/tools/petcat.ts +77 -0
- package/src/host/tools/status.ts +47 -0
- package/src/host/tools/version.ts +41 -0
- package/src/host/vice/adapter.ts +804 -0
- package/src/host/vice/binary-monitor.ts +389 -0
- package/src/host/vice/chips.ts +118 -0
- package/src/host/vice/connect.ts +34 -0
- package/src/host/vice/process.ts +413 -0
- package/src/host/vice/screen.ts +184 -0
- package/src/host/vice/session.ts +1426 -0
- package/src/host/vice/text-monitor.ts +223 -0
- package/src/host-client/autostart.ts +55 -0
- package/src/host-client/connect.ts +241 -0
- package/src/host-client/coverage.ts +63 -0
- package/src/host-client/steps.ts +170 -0
- package/src/host-client/tools.ts +89 -0
- package/src/host-client/transfer.ts +126 -0
- package/src/host-client/vice-session.ts +316 -0
- package/src/knowledge/database.ts +132 -0
- package/src/knowledge/history.ts +163 -0
- package/src/knowledge/import.ts +391 -0
- package/src/knowledge/read.ts +342 -0
- package/src/knowledge/schema.ts +229 -0
- package/src/knowledge/write.ts +663 -0
- package/src/mcp/main.ts +134 -0
- package/src/mcp/output.ts +32 -0
- package/src/mcp/server.ts +316 -0
- package/src/mcp/tools/debug.ts +327 -0
- package/src/mcp/tools/execution.ts +117 -0
- package/src/mcp/tools/input.ts +72 -0
- package/src/mcp/tools/machine.ts +100 -0
- package/src/mcp/tools/media.ts +129 -0
- package/src/mcp/tools/memory.ts +250 -0
- package/src/mcp/tools/video.ts +271 -0
- package/src/native/acme.ts +116 -0
- package/src/native/discover.ts +179 -0
- package/src/native/dxa.ts +166 -0
- package/src/native/ghidra/analyze.ts +86 -0
- package/src/native/ghidra/index.ts +173 -0
- package/src/native/ghidra/language/c64rt_6510.cspec +34 -0
- package/src/native/ghidra/language/c64rt_6510.ldefs +15 -0
- package/src/native/ghidra/language/c64rt_6510.pspec +15 -0
- package/src/native/ghidra/language/c64rt_6510.slaspec +596 -0
- package/src/native/ghidra/scripts/C64Export.java +274 -0
- package/src/native/ghidra/scripts/C64Prepare.java +60 -0
- package/src/native/local.ts +34 -0
- package/src/native/processes.ts +350 -0
- package/src/native/run.ts +172 -0
- package/src/native/staging.ts +83 -0
- package/src/native/status.ts +113 -0
- package/src/native/types.ts +257 -0
- package/src/native/watchdog.ts +78 -0
- package/src/package.ts +21 -0
- package/src/platform.ts +441 -0
- package/src/project.ts +39 -0
- package/src/protocol/framing.ts +132 -0
- package/src/protocol/messages.ts +259 -0
- package/src/protocol/tools.ts +266 -0
- package/src/protocol/vice.ts +1348 -0
- package/src/script.ts +60 -0
- package/src/time.ts +15 -0
- package/src/trace.ts +194 -0
- package/THIRD-PARTY-NOTICES.md +0 -26
- package/bin/cli.mjs +0 -283
- package/skills/acme-build/SKILL.md +0 -260
- package/skills/acme-build/scripts/acme.mjs +0 -341
- package/skills/acme-build/template.a +0 -53
- package/skills/c64-disk-access/SKILL.md +0 -159
- package/skills/c64-disk-access/scripts/c1541.mjs +0 -569
- package/skills/c64-memory-mapping/SKILL.md +0 -631
- package/skills/c64-memory-mapping/memmap.json +0 -8800
- package/skills/c64-memory-mapping/scripts/driver.mjs +0 -553
- package/skills/c64-petcat/SKILL.md +0 -87
- package/skills/c64-petcat/scripts/petcat.mjs +0 -221
- package/skills/c64-program-recon/SKILL.md +0 -706
- package/skills/c64-program-recon/references/control-flow.md +0 -180
- package/skills/c64-program-recon/references/graphics.md +0 -79
- package/skills/c64-program-recon/references/observation-hazards.md +0 -143
- package/skills/c64-program-recon/references/reconstruction.md +0 -133
- package/skills/c64-program-recon/references/sound-and-input.md +0 -74
- package/skills/c64-program-recon/references/tool-selection.md +0 -78
- package/skills/c64-program-recon/scripts/derive.mjs +0 -364
- package/skills/c64-program-recon/scripts/packer-finding.mjs +0 -709
- package/skills/c64-program-recon/templates/memory-map.template.md +0 -101
- package/skills/c64-provenance-diff/SKILL.md +0 -292
- package/skills/c64-provenance-diff/scripts/diff-images.mjs +0 -984
- package/skills/c64-provenance-diff/scripts/recovery-schema.mjs +0 -395
- package/skills/c64-ram-capture/RELEASES.json.example +0 -17
- package/skills/c64-ram-capture/SKILL.md +0 -474
- package/skills/c64-ram-capture/scripts/compare-cross-binary.mjs +0 -525
- package/skills/c64-ram-capture/scripts/compare.mjs +0 -258
- package/skills/c64-ram-capture/scripts/derive-transients.mjs +0 -575
- package/skills/c64-ram-capture/scripts/dump-artifacts.mjs +0 -317
- package/skills/c64-ram-capture/scripts/mcp-module.mjs +0 -174
- package/skills/c64-ram-capture/scripts/project-paths.mjs +0 -81
- package/skills/c64-ram-capture/scripts/releases.mjs +0 -109
- package/skills/c64-ram-capture/scripts/vsf-slice.mjs +0 -147
- package/skills/c64-ram-capture/scripts/watch-loads.mjs +0 -581
- package/skills/c64-ram-capture/templates/capture-record.template.md +0 -99
- package/skills/c64-ram-capture/transients/README.md +0 -137
- package/skills/routine-queue-walker/SKILL.md +0 -394
- package/skills/routine-queue-walker/scripts/completeness-report.mjs +0 -465
- package/skills/vice-wedge-triage/SKILL.md +0 -269
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// The typed tool dispatcher of the Host Runtime. The host runs only
|
|
2
|
+
// VICE and the tools that come with it (c1541, petcat); skill scripts run
|
|
3
|
+
// ACME, DXA and Ghidra themselves. One entry per operation, never a
|
|
4
|
+
// generic executable route.
|
|
5
|
+
|
|
6
|
+
import type { ViceVersion } from "../../native/discover.ts";
|
|
7
|
+
import type { ProcessSupervisor } from "../../native/processes.ts";
|
|
8
|
+
import type { ToolContext } from "../../native/run.ts";
|
|
9
|
+
import type { ToolOperation, ToolOperations } from "../../protocol/tools.ts";
|
|
10
|
+
import type { ToolDispatcher } from "../server.ts";
|
|
11
|
+
import { inspect } from "./c1541.ts";
|
|
12
|
+
import { decode } from "./petcat.ts";
|
|
13
|
+
import { hostStatus } from "./status.ts";
|
|
14
|
+
|
|
15
|
+
/** Runs one operation with its validated parameters and attachments. */
|
|
16
|
+
type Adapter<O extends ToolOperation> = (
|
|
17
|
+
params: ToolOperations[O]["params"],
|
|
18
|
+
attachments: Buffer[],
|
|
19
|
+
context: ToolContext,
|
|
20
|
+
) => Promise<{ result: ToolOperations[O]["result"]; attachments?: Buffer[] }>;
|
|
21
|
+
|
|
22
|
+
const ADAPTERS: { [O in ToolOperation]: Adapter<O> } = {
|
|
23
|
+
"host.status": (_params, _attachments, context) => hostStatus(context),
|
|
24
|
+
"c1541.inspect": (params, attachments, context) => inspect(params, attachments[0]!, context),
|
|
25
|
+
"petcat.decode": (_params, attachments, context) => decode(attachments[0]!, context),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** `vice`: the version that the host read from the emulator at start, for host.status. */
|
|
29
|
+
export function createToolDispatcher(options: { supervisor: ProcessSupervisor; env?: NodeJS.ProcessEnv; log?: (line: string) => void; vice?: ViceVersion }): ToolDispatcher {
|
|
30
|
+
return (op, params, attachments, signal) => {
|
|
31
|
+
const context = { supervisor: options.supervisor, signal, env: options.env, log: options.log };
|
|
32
|
+
if (op === "host.status") return hostStatus(context, options.vice) as ReturnType<ToolDispatcher>;
|
|
33
|
+
return ADAPTERS[op](params, attachments, context);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// The petcat adapter. petcat makes the C64 BASIC V2 listing; the
|
|
2
|
+
// adapter parses the tokenized program itself to check that listing and to
|
|
3
|
+
// find the machine-code handoffs, because petcat's exit status proves nothing
|
|
4
|
+
// (it prints any bytes as text).
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
import { findHandoffs, parseTokenized } from "../../c64.ts";
|
|
10
|
+
import { WireFailure } from "../../protocol/messages.ts";
|
|
11
|
+
import { type PetcatResult } from "../../protocol/tools.ts";
|
|
12
|
+
import { Workspace } from "../../native/staging.ts";
|
|
13
|
+
import { findTool, PETCAT } from "../../native/discover.ts";
|
|
14
|
+
import { requireMinimumVersion } from "./version.ts";
|
|
15
|
+
import { runToolOrFail, type ToolContext } from "../../native/run.ts";
|
|
16
|
+
|
|
17
|
+
const TIMEOUT_MS = 30_000;
|
|
18
|
+
const LISTING = "listing.txt";
|
|
19
|
+
/**
|
|
20
|
+
* petcat's listing lines (" 10 sys2061"), as number and text. petcat
|
|
21
|
+
* prints π ($ff) as `~`, which is no PETSCII character: the text has π (F-13).
|
|
22
|
+
*/
|
|
23
|
+
export function parseListing(listing: string): Array<{ number: number; text: string }> {
|
|
24
|
+
const lines: Array<{ number: number; text: string }> = [];
|
|
25
|
+
for (const line of listing.split(/\r?\n/)) {
|
|
26
|
+
if (line.trim() === "") continue;
|
|
27
|
+
const match = /^\s*(\d+) ?(.*)$/.exec(line);
|
|
28
|
+
if (match === null) throw new WireFailure("operation-failed", "petcat printed a listing line without a line number.");
|
|
29
|
+
lines.push({ number: Number(match[1]), text: match[2]!.replaceAll("~", "π") });
|
|
30
|
+
}
|
|
31
|
+
return lines;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function decode(
|
|
35
|
+
program: Buffer,
|
|
36
|
+
context: ToolContext,
|
|
37
|
+
): Promise<{ result: PetcatResult }> {
|
|
38
|
+
const tokenized = parseTokenized(program);
|
|
39
|
+
if ("reason" in tokenized) return { result: { decoded: false, reason: tokenized.reason } };
|
|
40
|
+
const executable = findTool(PETCAT, context.env);
|
|
41
|
+
await requireMinimumVersion(PETCAT, executable, context);
|
|
42
|
+
// petcat gets the BASIC text only, closed with a real end marker: after a
|
|
43
|
+
// link that only ends BASIC (machine code right after the last line), petcat
|
|
44
|
+
// prints a comment line where a listing line belongs.
|
|
45
|
+
const text = Buffer.concat([program.subarray(0, tokenized.textBytes), Buffer.of(0, 0)]);
|
|
46
|
+
const workspace = Workspace.create(context.supervisor);
|
|
47
|
+
try {
|
|
48
|
+
workspace.materialize("input", [{ path: "program.prg", size: text.length }], [text]);
|
|
49
|
+
const listingPath = join(workspace.directory("out"), LISTING);
|
|
50
|
+
const run = await runToolOrFail(
|
|
51
|
+
"petcat",
|
|
52
|
+
"The BASIC decode",
|
|
53
|
+
// -2: C64 BASIC V2 keywords. -nh: no header. The input is never read as an option.
|
|
54
|
+
{ argv: [executable, "-2", "-nh", "-o", listingPath, "--", "input/program.prg"], cwd: workspace.root, timeoutMs: TIMEOUT_MS },
|
|
55
|
+
context,
|
|
56
|
+
);
|
|
57
|
+
if (run.code !== 0 || !existsSync(listingPath)) {
|
|
58
|
+
context.log?.(`petcat exited ${run.code}:\n${run.stdout}\n${run.stderr}`);
|
|
59
|
+
throw new WireFailure("operation-failed", "petcat could not decode the program.");
|
|
60
|
+
}
|
|
61
|
+
const lines = parseListing(readFileSync(listingPath, "latin1"));
|
|
62
|
+
const agrees = lines.length === tokenized.lines.length && lines.every((line, index) => line.number === tokenized.lines[index]!.number);
|
|
63
|
+
if (!agrees) throw new WireFailure("operation-failed", "petcat's listing does not match the lines of the program.");
|
|
64
|
+
return {
|
|
65
|
+
result: {
|
|
66
|
+
decoded: true,
|
|
67
|
+
loadAddress: tokenized.loadAddress,
|
|
68
|
+
basicEnd: tokenized.basicEnd,
|
|
69
|
+
listing: lines.map((line) => `${line.number} ${line.text}`).join("\n"),
|
|
70
|
+
lines,
|
|
71
|
+
handoffs: findHandoffs(tokenized.lines),
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
} finally {
|
|
75
|
+
workspace.remove();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// host.status: VICE and the tools that come with it, each found the way its
|
|
2
|
+
// operations find it and run once with a version option. A tool from a
|
|
3
|
+
// VICE older than MIN_VICE is reported as not working, as its operations refuse it.
|
|
4
|
+
// VICE itself is reported with the version that the host read from the
|
|
5
|
+
// running emulator at start: the Homebrew x64sc of VICE 3.10 on macOS stops
|
|
6
|
+
// on -version ("argv[0] is NULL") although the emulator runs.
|
|
7
|
+
|
|
8
|
+
import { arch, platform, release } from "node:os";
|
|
9
|
+
|
|
10
|
+
import { PACKAGE } from "../../package.ts";
|
|
11
|
+
import type { HostInfo, ToolStatus } from "../../protocol/tools.ts";
|
|
12
|
+
import { C1541, findTool, isOlderThanMinimum, MIN_VICE, PETCAT, VICE, viceFlaws, viceVersionOf, type ToolSpec, type ViceVersion } from "../../native/discover.ts";
|
|
13
|
+
import type { ToolContext } from "../../native/run.ts";
|
|
14
|
+
import { probeTools } from "../../native/status.ts";
|
|
15
|
+
import { findVice } from "../vice/process.ts";
|
|
16
|
+
|
|
17
|
+
function requireMinimum(status: ToolStatus, tool: ToolSpec): ToolStatus {
|
|
18
|
+
if (!status.runs) return status;
|
|
19
|
+
const version = viceVersionOf(status.version ?? "");
|
|
20
|
+
if (version !== undefined && !isOlderThanMinimum(version)) return status;
|
|
21
|
+
const found = version === undefined ? "It does not tell its VICE version" : `It comes from VICE ${version.major}.${version.minor}`;
|
|
22
|
+
return { ...status, runs: false, problem: `${found}, and c64-re-tools needs VICE ${MIN_VICE.major}.${MIN_VICE.minor} or later. ${tool.remedy}` };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The version text of a VICE version, as x64sc -version prints it. */
|
|
26
|
+
const versionText = (version: ViceVersion) => `x64sc (VICE ${version.major}.${version.minor}${version.revision === undefined ? "" : ` SVN r${version.revision}`})`;
|
|
27
|
+
|
|
28
|
+
/** `started`: the version that the host read from the emulator at start; without it, VICE is probed with -version too. */
|
|
29
|
+
export async function hostStatus(context: ToolContext, started?: ViceVersion): Promise<{ result: { host: HostInfo; tools: ToolStatus[] } }> {
|
|
30
|
+
const specs = [VICE, C1541, PETCAT];
|
|
31
|
+
const probed = await probeTools(
|
|
32
|
+
[
|
|
33
|
+
...(started === undefined ? [{ name: VICE.name, find: findVice, args: ["-version"], pattern: /^x64sc \(VICE \d/ }] : []),
|
|
34
|
+
{ name: C1541.name, find: (env) => findTool(C1541, env), args: ["-version"], pattern: /^c1541 \(VICE \d/ },
|
|
35
|
+
{ name: PETCAT.name, find: (env) => findTool(PETCAT, env), args: ["-version"], pattern: /^petcat \(VICE \d/ },
|
|
36
|
+
],
|
|
37
|
+
context,
|
|
38
|
+
);
|
|
39
|
+
const tools = started === undefined ? probed : [{ name: VICE.name, found: true, path: findVice(context.env ?? process.env), version: versionText(started), runs: true }, ...probed];
|
|
40
|
+
const checked = tools.map((status, index) => requireMinimum(status, specs[index]!));
|
|
41
|
+
// VICE runs with its known flaws; status names them (D56).
|
|
42
|
+
const vice = checked[0]!;
|
|
43
|
+
const version = vice.runs ? viceVersionOf(vice.version ?? "") : undefined;
|
|
44
|
+
const flaws = version === undefined ? [] : viceFlaws(version);
|
|
45
|
+
if (flaws.length > 0) checked[0] = { ...vice, flaws };
|
|
46
|
+
return { result: { host: { version: PACKAGE.version, platform: platform(), release: release(), arch: arch() }, tools: checked } };
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// The VICE tools on the host must come from a VICE that c64-re-tools works
|
|
2
|
+
// with. Each executable is asked once for its version; a version that
|
|
3
|
+
// cannot be read is refused, as is one that is too old.
|
|
4
|
+
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
|
|
7
|
+
import { WireFailure } from "../../protocol/messages.ts";
|
|
8
|
+
import { isOlderThanMinimum, MIN_VICE, viceVersionOf, type ToolSpec } from "../../native/discover.ts";
|
|
9
|
+
import { runToolOrFail, type ToolContext } from "../../native/run.ts";
|
|
10
|
+
|
|
11
|
+
const VERSION_TIMEOUT_MS = 30_000;
|
|
12
|
+
const checked = new Map<string, Promise<void>>();
|
|
13
|
+
|
|
14
|
+
/** Refuses a tool from a VICE older than MIN_VICE, or one whose VICE version cannot be read, by name and with the remedy. */
|
|
15
|
+
export function requireMinimumVersion(tool: ToolSpec, executable: string, context: ToolContext): Promise<void> {
|
|
16
|
+
let check = checked.get(executable);
|
|
17
|
+
if (check === undefined) {
|
|
18
|
+
// Every caller waits for the same check, so no caller's cancel may stop it; its own time limit bounds it.
|
|
19
|
+
const shared: ToolContext = { ...context, signal: new AbortController().signal };
|
|
20
|
+
check = (async () => {
|
|
21
|
+
const run = await runToolOrFail(tool.name, `The ${tool.name} version check`, { argv: [executable, "-version"], cwd: tmpdir(), timeoutMs: VERSION_TIMEOUT_MS }, shared);
|
|
22
|
+
const version = viceVersionOf(`${run.stdout}\n${run.stderr}`);
|
|
23
|
+
if (version === undefined) {
|
|
24
|
+
throw new WireFailure(
|
|
25
|
+
"installation-incomplete",
|
|
26
|
+
`${tool.name} does not tell its VICE version, and c64-re-tools needs VICE ${MIN_VICE.major}.${MIN_VICE.minor} or later. ${tool.remedy}`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (isOlderThanMinimum(version)) {
|
|
30
|
+
throw new WireFailure(
|
|
31
|
+
"installation-incomplete",
|
|
32
|
+
`${tool.name} comes from VICE ${version.major}.${version.minor}, and c64-re-tools needs VICE ${MIN_VICE.major}.${MIN_VICE.minor} or later. ${tool.remedy}`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
// A refusal or a failed check is asked again next time: the user can install a newer VICE meanwhile.
|
|
37
|
+
check.catch(() => checked.delete(executable));
|
|
38
|
+
checked.set(executable, check);
|
|
39
|
+
}
|
|
40
|
+
return check;
|
|
41
|
+
}
|