IBM Z® Open Editor
Docs
News and Blogs
IBM Downloads
VS Code Marketplace
GitHub
Docs
News and Blogs
IBM Downloads
VS Code Marketplace
GitHub
  • What's New

    • New Content and Blog Posts
    • IBM Z Open Editor Releases
  • Team Blog

    • No More Asking a Robot to Read Your Code for You: Native PL/I Macro Support in Z Open Editor 6.7.0
    • Using the IBM® RSE API Plug-in for Zowe™ CLI as a Node.js SDK
    • COBOL and PL/I preprocessor support by IBM Z® Open Editor
    • Managing data sets, jobs, and UNIX files in Z Open Editor with the z/OS Resources Table
    • A Modern JCL (Job Control Language) Editor
    • Scaling up the audience with IBM Z Open Editor and Wazi Developer 1.2.0
    • A Modern REXX Editor
    • Everything you need to know about IBM RSE API Plug-in for Zowe CLI 1.2.0
    • IBM Z® Open Editor makes building COBOL, PL/I, and HLASM applications easier with User Build
    • IBM Wazi Developer for Red Hat CodeReady Workspaces: Set up an SSL Certificate in an OpenShift Container Platform
    • What's new with IBM RSE API Plug-in for Zowe CLI 1.1.0
    • Kubernetes-Native Integrated Z Developer Environment with IBM Wazi for Red Hat CodeReady Workspaces Development Client
    • IBM Z Open Editor: A modern IDE for IBM High Level Assembler
    • Interacting with z/OS using IBM RSE API Plug-in for Zowe CLI
    • Improve your z/OS enterprise developer productivity with IBM Z Open Editor‘s code snippets library
    • IBM Z® Open Editor in the cloud with Eclipse Che
    • Running IBM Z® Open Editor in the browser with Eclipse Theia
  • Other Resources

    • Learning Resources

No More Asking a Robot to Read Your Code for You: Native PL/I Macro Support in Z Open Editor 6.7.0

If you write PL/I for IBM Z®, you have probably stared at your editor and thought: "Why is it yelling at me? This code compiles fine."

The answer, almost certainly, is macros.

The old approach (a.k.a. "please hold while we outsource your parsing")

PL/I's macro preprocessor is powerful. Before the compiler sees your code, a preprocessing step evaluates %IF/%THEN/%ELSE branches, expands %DECLAREd variables, calls %PROCEDUREs, and produces a clean stream of plain PL/I for the compiler to process.

The editor, however, was not the compiler. It saw what you typed, raw macros and all, and had to make sense of it. The workaround has long been a configurable external preprocessor: point the editor to a local binary or a remote preprocessor running on z/OS®, and it runs your source through the preprocessor, compares the result with the original source, and:

  • Color the original source to show which tokens change after preprocessing
  • Shows the preprocessed text in a hover on those highlighted tokens
  • Report errors only against the preprocessed output, so squiggly red lines reflect real compiler errors rather than complaints about unexpanded directives

This approach still works, and it remains available. However, it has a limitation that frustrated many users: macro declarations and procedure definitions all received the same flat color, and hovering over them showed what a token expanded to — but not why. The preprocessor expands them away entirely, so the diff can only indicate that they are gone. You could see the output, but not the meaning: not what type a variable was, not what value it currently held, and not where a procedure was declared.

What changed in 6.7.0

We built a native macro preprocessor directly into the editor. No external binary, remote connection, or configuration is required. Open a .pli file and the editor understands your macros right out of the box.

More than simply eliminating setup friction, the native preprocessor provides a significantly better editing experience:

Semantically-aware syntax coloring. Macro variables, macro procedure declarations, and regular PL/I code are each colored distinctly and correctly because the editor now understands what each token is, not just that it differs from external output.

Rich, live hover information. Hover over a %DECLAREd variable and see its type and current value at that point in the file. Hover over a macro procedure and see the procedure signature. The information reflects the actual macro state rather than a diff artifact.

Go to Declaration for macros. You can now navigate to the declaration of a macro variable or procedure in the same as any other PL/I symbol. Click through, jump back. It works exactly as expected.

Errors that make sense. Invalid or incorrect macro directives are flagged directly where they appear, and errors in the resulting code are reported against the post-preprocessed view so that every diagnostic reflects an actual issue.

A quick example

Here is the classic "ZIP code lookup" example from the PL/I Programming Guide, a source file that uses %IF/%ELSE to emit either a function or a subroutine depending on a macro variable:

 %DCL USE CHAR;
 %USE = 'SUB';   /* 'FUN' for a function, 'SUB' for a subroutine */

 %IF USE = 'FUN' %THEN %DO;
   CITYFUN: PROC(ZIPIN) RETURNS(CHAR(16)) REORDER;
 %END;
 %ELSE %DO;
   CITYSUB: PROC(ZIPIN, CITYOUT) REORDER;
   DCL CITYOUT CHAR(16);
 %END;

   DCL ZIPIN PIC '99999';
  ...

Without a preprocessor configured, the editor sees both procedure declarations simultaneously and flags them as conflicting errors because, from the raw parser's point of view, both branches appear to be active at the same time.

With the external preprocessor configured, those errors disappear because the editor receives the post-processed output and knows which branch was taken. Hovering over a highlighted token shows what it expanded to, but not why. %USE, %DCL, and the CITYSUB: label all receive the same flat coloring, and because the preprocessor expands them away entirely, the diff can only indicate that they are gone. It cannot tell the editor what they represent, what type USE is, or what its current value is.

With the native preprocessor, the editor evaluates %USE = 'SUB', takes the correct branch, and shows you only CITYSUB, with proper semantic coloring for every macro token, a hover on USE that shows its type and current value 'SUB', and Go to Declaration support for both the variable and the procedure. No false errors appear, and no context is lost.

PLI macro hover

What the native preprocessor handles

The implementation supports the full standard PL/I macro language:

CategoryWhat's supported
Variable declarations%DECLARE / %DCL — scalar and array CHAR and FIXED variables
Assignment%var = expr; with full expression evaluation
Conditionals%IF / %THEN / %ELSE / %DO / %END
Loops%DO...%END with %ITERATE and %LEAVE
Control flow%GOTO
Macro procedures%label: PROC(...) [RETURNS(type)]; with ANSWER/ANS and RETURN
Activation%ACTIVATE / %DEACTIVATE with SCAN, RESCAN, NORESCAN
Built-in functionsAll 30+ standard preprocessor built-ins: COLLATE, COPY, COUNTER, DIMENSION, HBOUND, LBOUND, INDEX, LENGTH, LOWERCASE, UPPERCASE, MAX, MIN, SUBSTR, TRIM, TRANSLATE, VERIFY, SYSPARM, SYSTEM, SYSVERSION, COMPILEDATE, COMPILETIME, MACNAME, PARMSET, and more
Compiler options%PROCESS directives: MACRO(CASE(...)), MACRO(DBCS(...)), MACRO(FIXED(...)), MACRO(RESCAN(...)), LP(32|64), SYSPARM(...), CMPAT(...)

What about the external preprocessor?

The external preprocessor option is not going away. It remains the right tool for one important use case: non-standard preprocessing. If your codebase uses custom macros or preprocessing syntax beyond what the PL/I compiler natively defines, the external preprocessor remains the mechanism that handles it.

However, if you use the external preprocessor only for standard PL/I macro expansion, we strongly encourage you to disable it. Running both means that you lose the richer editor experience described earlier. The result is flat coloring, the empty hovers on declarations, and no Go to Declaration support.

If you use only standard PL/I macros: Disable the external preprocessor in your project settings and let the native support take over. This approach provides improved coloring, live hovers, and navigation.

If you use non-standard preprocessing: Check whether the preprocessor can be configured to skip standard macro processing and handle only the custom parts. If it can, you get the best of both worlds: native editor support for standard macros and external preprocessing support for custom syntax.

Availability

Native PL/I macro preprocessor support is available in ZOpen Editor 6.7.0 and will be available in IBM Developer for z/OS 18.0.0.


What other PL/I editing features would make a difference to your daily work? Share your feedback in the comments.

Last Updated: 9/24/26, 4:19 PM
Contributors: RUSS MAY, Esther M, phaumer
Next
Using the IBM® RSE API Plug-in for Zowe™ CLI as a Node.js SDK