Message Handling
CL error handling centers on MONMSG (monitor message) and outbound messaging via SNDMSG / SNDPGMMSG. Extracting monitors and their EXEC bodies is a common first step for reliability reviews and migration of exception paths.
Add Dependencies
- Kotlin
- Java
repositories {
mavenLocal()
mavenCentral()
flatDir {
dirs("deps")
}
}
dependencies {
implementation(files("deps/clparser-with-dependencies-1.0.1-all.jar"))
}
repositories {
mavenLocal()
mavenCentral()
flatDir {
dirs("deps")
}
}
dependencies {
implementation(files("deps/clparser-with-dependencies-1.0.1-all.jar"))
implementation "com.strumenta.kolasu:kolasu-javalib:1.5.107"
}
List MONMSG monitors and EXEC bodies
MonitorMessageCommand carries message ids in msgid. Nested EXEC(...) commands appear as CLExecKeyword entries among the command parameters (including EXEC(DO)…ENDDO groups after control-flow nesting).
- Kotlin
- Java
import com.strumenta.cl.model.CLExecKeyword
import com.strumenta.cl.model.CLExpression
import com.strumenta.cl.model.CLLiteral
import com.strumenta.cl.model.CLReferenceExpr
import com.strumenta.cl.model.MonitorMessageCommand
import com.strumenta.cl.model.SendMessageCommand
import com.strumenta.cl.model.SendProgramMessageCommand
import com.strumenta.cl.parser.CLKolasuParser
import com.strumenta.kolasu.commercial.LicenseManager
import com.strumenta.kolasu.traversing.walkDescendants
import java.io.File
fun formatExpr(expr: CLExpression?): String =
when (expr) {
is CLReferenceExpr -> expr.name.name
is CLLiteral -> expr.text
null -> "?"
else -> expr.toString()
}
fun printMessageHandling(clFile: File, license: File) {
LicenseManager.registerLicense(license)
val root = CLKolasuParser().parse(clFile).root ?: return
println("MONMSG:")
root.walkDescendants(MonitorMessageCommand::class).forEach { mon ->
val ids = mon.msgid.joinToString { formatExpr(it) }
println(" msgids=[$ids]")
mon.parameters.filterIsInstance<CLExecKeyword>().forEach { exec ->
println(" EXEC → ${exec.command.simpleNodeType}")
}
}
val sndMsg = root.walkDescendants(SendMessageCommand::class).count()
val sndPgmMsg = root.walkDescendants(SendProgramMessageCommand::class).count()
println("SNDMSG: $sndMsg")
println("SNDPGMMSG: $sndPgmMsg")
}
import com.strumenta.cl.model.CLCompilationUnit;
import com.strumenta.cl.model.CLExecKeyword;
import com.strumenta.cl.model.CLExpression;
import com.strumenta.cl.model.CLLiteral;
import com.strumenta.cl.model.CLReferenceExpr;
import com.strumenta.cl.model.MonitorMessageCommand;
import com.strumenta.cl.model.SendMessageCommand;
import com.strumenta.cl.model.SendProgramMessageCommand;
import com.strumenta.cl.parser.CLKolasuParser;
import com.strumenta.kolasu.commercial.LicenseManager;
import com.strumenta.kolasu.javalib.Traversing;
import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class MessageHandling {
public static String formatExpr(CLExpression expr) {
if (expr instanceof CLReferenceExpr ref) return ref.getName().getName();
if (expr instanceof CLLiteral lit) return lit.getText();
return expr == null ? "?" : expr.toString();
}
public static void printMessageHandling(File clFile, File license) {
LicenseManager.INSTANCE.registerLicense(license);
CLCompilationUnit root = new CLKolasuParser().parse(clFile).getRoot();
if (root == null) return;
System.out.println("MONMSG:");
Traversing.walkDescendantsBreadthFirst(root, MonitorMessageCommand.class, mon -> {
String ids = mon.getMsgid().stream()
.map(MessageHandling::formatExpr)
.collect(Collectors.joining(", "));
System.out.println(" msgids=[" + ids + "]");
mon.getParameters().stream()
.filter(CLExecKeyword.class::isInstance)
.map(CLExecKeyword.class::cast)
.forEach(exec -> System.out.println(
" EXEC → " + exec.getCommand().getSimpleNodeType()));
});
AtomicInteger sndMsg = new AtomicInteger();
AtomicInteger sndPgmMsg = new AtomicInteger();
Traversing.walkDescendantsBreadthFirst(root, SendMessageCommand.class, c -> sndMsg.incrementAndGet());
Traversing.walkDescendantsBreadthFirst(root, SendProgramMessageCommand.class, c -> sndPgmMsg.incrementAndGet());
System.out.println("SNDMSG: " + sndMsg.get());
System.out.println("SNDPGMMSG: " + sndPgmMsg.get());
}
}
Combine this with control-flow aware walks when EXEC(DO) wraps multiple recovery commands, and with program inventory when estimating exception-handling density across a library.