RPGLE calculation specs are where traditional RPG programs expressed executable work: calculations, assignments, decisions, loops, calls, and certain input or output operations.
In older source, that work appears on position-dependent C-specification lines.
In modern fully free-form RPGLE, the same responsibilities appear as readable statements and expressions.
This is primarily a maintenance lesson about recognizing legacy code.
Do not use its fixed-format excerpt as a template for new development.
New RPGLE should generally use fully free-form syntax.
The previous lesson, RPGLE Input and Output Specifications Explained, separated record descriptions from the operations that move or change data.
This lesson follows that boundary into the executable logic itself.
It retains the canonical intermediate classification while explaining each idea in beginner-friendly terms for readers entering early-intermediate maintenance work.
Estimated reading time: 11 to 14 minutes
Quick Summary
- A traditional calculation specification, commonly called a C-spec, describes an operation performed on program data.
- The operation code is the verb: it tells you whether a line calculates, assigns, compares, branches, repeats, calls, or performs another action.
- Fixed-format fields and column positions matter when reading legacy C-specs.
- Modern fully free-form RPGLE expresses the same responsibilities with statements, expressions, built-in functions, and procedure calls.
- A modernization is a behavior-preserving translation, not necessarily a one-line replacement.
- Learn C-specs so you can maintain older applications; write new logic in fully free-form RPGLE.

Both lanes perform the same broad job: input data enters a business rule, and a result or action comes out.
The representation changed; the logical responsibility remains.
Reader Prerequisites
You should already recognize the major sections of an RPGLE program.
RPGLE Program Structure Explained provides that foundation, and RPGLE Specifications: Fixed, Free, and Fully Free explains the source forms you may encounter.
You do not need to memorize fixed-format columns, indicator numbers, operation extenders, or the RPG program cycle.
The goal is to classify a calculation before looking up its exact rules.
Learning Outcomes
By the end of this lesson, you will be able to:
- explain what traditional calculation specifications were responsible for;
- recognize the broad shape of a fixed-format C-spec line;
- find the operation code, operands, result, and surrounding logic block;
- map common legacy responsibilities to modern fully free-form syntax;
- follow
IF,SELECT,DOW,DOU, andFORblocks; - recognize older subroutine and call patterns without adopting them by default; and
- use a safe workflow before changing legacy business logic.
What Calculation Specifications Were
IBM describes calculation specifications as the part of RPG that identifies operations performed on data.
Their order also defines the order in which those calculations run.2
In the traditional main source sequence, calculation specifications follow input specifications and precede output specifications.1
“Calculation” is broader than arithmetic.
A C-spec could:
- multiply quantity by price;
- assign or move a value;
- compare two fields;
- choose one branch of a business rule;
- repeat a group of operations;
- invoke a subroutine or call another program; or
- request certain program-controlled file operations.
That is why this lesson uses the phrase calculation and business logic.
The C-specification area was the executable center of many traditional RPG programs, not merely a place for addition and subtraction.
The full history also includes detail calculations, total calculations, and cycle-related behavior.
Those topics are important in some legacy applications, but they are not required to understand the basic responsibility map here.
How to Recognize a Legacy Fixed-Format C-Spec
In traditional syntax, C identifies the calculation specification type.
The rest of the record is divided into position-dependent areas for conditions, factor 1, the operation code, factor 2 or an extended expression, the result field, and possible resulting indicators.3
Here is the small recognition excerpt used throughout this lesson:
* Legacy fixed-format recognition excerpt only.
* Preserve columns; do not use this as a new-code template.
C Quantity MULT UnitPrice LineTotal
C IF LineTotal > 100
C EVAL HighValue = *ON
C ENDIF
This excerpt is intentionally incomplete.
Its fields would be declared elsewhere, and the exact column placement must be preserved.
Read it in this order:
- Find the operation code:
MULT,IF,EVAL, orENDIF. - Read the operands and result around that operation.
- Match the opening
IFwith its closingENDIF. - Check any conditioning or resulting-indicator positions last.
The first line multiplies Quantity by UnitPrice and places the product in LineTotal.
The block then sets HighValue on when the total is greater than 100.
For quantity 5 and unit price 25.00, the expected total is 125.00, so the condition is true.
The reusable excerpt is stored at content/code/rpgle/article-056/legacy-line-total-c-specs.rpgle.
It exists for recognition practice, not compilation or copying into new programs.
What Operation Codes Did
An operation code is the verb of a calculation line.
It tells you what kind of work to investigate before you become distracted by field names or indicators.
| Operation family | Legacy examples you may see | Responsibility to identify |
|---|---|---|
| Arithmetic | ADD, SUB, MULT, DIV | Produce a numeric result |
| Assignment and movement | EVAL, MOVE, MOVEL | Put or reshape a value in a target |
| Decisions | IF, older IFxx forms, SELECT, WHEN | Choose which operations run |
| Iteration | DOW, DOU, FOR | Repeat a structured group |
| Reuse and calls | EXSR, CALL, CALLP | Transfer control to reusable logic |
| File work | READ, CHAIN, WRITE, and others | Request program-controlled I/O |
Some operation names, including IF, SELECT, DOW, DOU, and FOR, remain available in free-form calculations.
Other older operations have clearer modern forms.
IBM’s arithmetic map, for example, associates MULT with the * operator, while its movement guidance maps MOVE or MOVEL responsibilities toward evaluation or conversion facilities.5 6
Do not treat the table as an automatic converter.
An old operation may carry rounding, padding, truncation, extender, or indicator behavior that a simple replacement would lose.
Arithmetic and Assignment: From Result Fields to Expressions
The modern equivalent of the sample’s arithmetic responsibility is direct:
lineTotal = quantity * unitPrice;
The target appears on the left, and the expression appears on the right.
The complete rule is visible without aligning factor and result fields.
In a free-form calculation statement, EVAL can normally be omitted when no extender is required and the target name does not conflict with an operation code.4
That is why new code usually uses lineTotal = ...; instead of eval lineTotal = ...;.
The free-form equivalent of the complete small rule is:
lineTotal = quantity * unitPrice;
if lineTotal > 100;
highValue = *on;
endif;
The repository version at content/code/rpgle/article-056/modern-line-total.rpgle supplies declarations and initialized values.
It produces lineTotal = 125.00 and highValue = *ON.
Simple arithmetic mappings are easy to recognize:
| Legacy responsibility | Modern expression direction |
|---|---|
| Add | total = amountA + amountB; |
| Subtract | balance = balance - payment; or balance -= payment; |
| Multiply | lineTotal = quantity * unitPrice; |
| Divide | average = total / count; after handling a possible zero count |
Movement operations need more care.
MOVE and MOVEL can involve alignment, padding, truncation, and type conversion.
Before replacing one, confirm the source and target types and read the operation’s IBM reference.
Modern assignment plus an explicit conversion or string operation is usually easier to understand, but it must preserve the intended behavior.
Comparisons and Conditional Logic
A comparison asks a true-or-false question such as lineTotal > 100.
A conditional block uses that answer to control which statements run.
IF and ELSE
Use IF when the rule has a primary path and perhaps an alternative:
if customerActive and balanceDue > 0;
action = 'SEND';
else;
action = 'HOLD';
endif;
The statements inside the first branch run only when the expression is true.
ELSE supplies the alternative, and ENDIF closes the block.7
This runtime IF is not the compile-time /IF directive introduced in RPGLE Control Specifications and Compiler Directives.
One chooses source during compilation; the other chooses work while the program runs.
SELECT, WHEN, and OTHER
Use SELECT when several mutually exclusive outcomes make one long IF chain difficult to scan:
select;
when subtotal >= 400.00;
discountRate = 0.1000;
when subtotal >= 250.00;
discountRate = 0.0500;
other;
discountRate = 0;
endsl;
RPG evaluates the alternatives in order and processes the first satisfied WHEN branch.
OTHER handles the case in which none of the earlier conditions is satisfied, and ENDSL closes the group.7
Older code may express comparisons through resulting indicators or conditional operation-code forms.
Resulting indicators belong to traditional C-spec syntax, not free-form calculation specifications; IBM notes that built-in functions can replace them in many cases.9
Do not remove an indicator until you can say in plain language what status it carries.
The planned next lesson, RPGLE Indicators and Status Flags, explores that maintenance problem directly.
Loops and Iteration
Loops repeat a group of statements.
The important first question is not “Which loop is best?” but “When is the condition tested, and what ends the repetition?”
DOW and DOU
DOW repeats while its condition is true and can run zero times.
DOU repeats until its condition becomes true and runs its group at least once.
Both close with ENDDO.7
dow itemsRemaining > 0;
itemsRemaining -= 1;
enddo;
dou responseValid;
responseValid = validateResponse();
enddo;
The second micro-example assumes a separately defined procedure named validateResponse.
It illustrates loop shape only.
FOR
FOR is a clear choice when a counter moves through a known range:
for lineIndex = 1 to %elem(lineAmounts);
subtotal += lineAmounts(lineIndex);
endfor;
%ELEM supplies the number of elements in the array, so the loop limit stays aligned with its declared size.8
ENDFOR makes the block boundary explicit.
When reading any loop, locate the opener, closer, exit condition, changed variables, and side effects before editing it.
Subroutines, Calls, and Modern Modular Logic
Legacy programs often group calculations between BEGSR and ENDSR, then invoke that group with EXSR.
These operations remain recognizable in free-form syntax, so it would be inaccurate to say that fully free-form RPGLE forbids subroutines.10
For new modular logic, prefer a clearly named procedure with an explicit interface where parameters or a return value are needed.
A modern call can read like an ordinary statement or expression:
discountAmount = calculateDiscount(subtotal);
IBM recommends prototyped calls over older CALL/CALLB and PARM/PLIST patterns.
Prototypes allow the compiler to check the call interface, and the caller passes arguments on the call itself.11
Do not convert an EXSR mechanically.
First identify which fields the subroutine reads or changes, whether it depends on global state, where it can leave early, and how errors return to the caller.
Those observations become the candidate procedure’s parameters, return value, and error contract.
Map Legacy Responsibilities to Modern RPGLE
Use this table as a reading guide, not a promise of one-to-one conversion:
| Traditional pattern to recognize | Responsibility | Modern fully free-form direction |
|---|---|---|
EVAL or a result-producing calculation | Assign or calculate | target = expression; |
MOVE or MOVEL | Transfer or reshape data | Explicit assignment plus the verified conversion or string operation |
ADD, SUB, MULT, or DIV | Arithmetic | +, -, *, /, or a clear compound assignment |
COMP and indicators, or older conditional operations | Compare and choose | Boolean expression in IF, ELSEIF, or SELECT |
IF / ELSE / ENDIF | Conditional flow | The corresponding free-form structured block |
SELECT / WHEN / OTHER / ENDSL | Multiple alternatives | The corresponding free-form selection group |
DOW / DOU / ENDDO | Conditional iteration | A free-form loop with an explicit condition |
| Counted repetition | Visit a known range | FOR / ENDFOR |
| Resulting indicators | Carry a condition or operation status | A named boolean expression or relevant built-in function where documented |
EXSR with BEGSR / ENDSR | Reuse an in-program group | A clearly named procedure when creating new modular logic |
CALL with PARM | Call another program with an older interface | A prototyped call with arguments on the call |
The safe sequence is responsibility first, syntax second, behavior verification last.
Build a Modern Pricing Logic Block
The larger teaching sample uses four in-memory line amounts.
It totals the array, chooses a discount, and calculates the final amount.
There is no database, file, indicator, or external-service dependency.
lineAmounts(1) = 50.00;
lineAmounts(2) = 75.00;
lineAmounts(3) = 125.00;
lineAmounts(4) = 150.00;
for lineIndex = 1 to %elem(lineAmounts);
subtotal += lineAmounts(lineIndex);
endfor;
select;
when subtotal >= 400.00;
discountRate = 0.1000;
when subtotal >= 250.00;
discountRate = 0.0500;
other;
discountRate = 0;
endsl;
discountAmount = subtotal * discountRate;
finalTotal = subtotal - discountAmount;
Read the block in three passes:
- The
FORloop adds50.00 + 75.00 + 125.00 + 150.00, producingsubtotal = 400.00. - The first
WHENis true, sodiscountRate = 0.1000. - The calculation produces
discountAmount = 40.00andfinalTotal = 360.00.
The complete sample is at content/code/rpgle/article-056/modern-order-pricing.rpgle.
Its descriptive names, initialized values, shallow nesting, and stated result make the business rule testable without unrelated infrastructure.
Common Beginner Mistakes
- Calling all executable RPGLE “C-specs.” Modern fully free-form calculations are statements; reserve C-spec for the traditional calculation-specification context.
- Ignoring fixed-format spacing. Columns carry meaning in a traditional C-spec, even when a rendered excerpt looks like loosely spaced text.
- Reading field names before the verb. Start with the operation code, then interpret its operands and result.
- Converting one line at a time. A line may depend on surrounding indicators, block boundaries, shared fields, extenders, or subroutines.
- Treating
DOWandDOUas interchangeable. They test different continuation conditions and have different minimum execution counts. - Confusing
IFwith/IF.IFcontrols runtime logic;/IFcontrols conditional compilation. - Replacing
MOVEwith=without checking behavior. Alignment, padding, truncation, and conversion can change the result. - Assuming indicators are meaningless noise. Give each one a plain-language meaning before deciding whether a boolean expression or built-in function should replace it.
- Using
EXSRfor every new reusable rule. Procedures provide a clearer modular direction for new code. - Adding database logic to learn control flow. Isolate the business rule first; file access deserves its own lesson and tests.
A Practical Legacy-Maintenance Workflow
Use this process before changing calculation logic:
- Identify the source form. Look for fixed-format records, column-limited free-form blocks,
**free, and included copy source. - Locate the procedure. Separate declarations from the executable body and confirm whether you are in the main procedure, a subprocedure, or a subroutine.
- Classify each operation. Mark it as assignment, arithmetic, decision, loop, call, I/O, or another side effect.
- Match every block. Pair
IFwithENDIF,SELECTwithENDSL, loop openers with their endings, andBEGSRwithENDSR. - Translate conditions into words. “Indicator 42 is on” is less useful than “the customer record was found.” Confirm that meaning from every place the indicator is set and tested.
- Trace important fields. Find where a total, status, or key value is assigned, changed, and consumed.
- List side effects. Record calls, subroutines, file operations, messages, and state changes outside the apparent block.
- Check exact semantics. Use IBM’s operation reference for extenders, data types, rounding, truncation, errors, and status behavior.
- Preserve behavior with tests. Capture representative inputs and expected outputs before restructuring.
How to Read an RPGLE Program From Top to Bottom provides the broader reading pass that surrounds this calculation-focused workflow.
FAQ
What is a C-spec in RPGLE?
A C-spec is a traditional calculation specification.
It uses a position-dependent record to express an operation, its operands or expression, its result, and sometimes conditions or resulting indicators.
Are calculation specifications still used in modern RPGLE?
The calculation responsibility still exists, but new fully free-form RPGLE expresses it with statements and expressions rather than traditional fixed-format C-spec records.
Older and mixed-form applications can still contain C-specs, so maintainers need to recognize them.
How do I recognize a fixed-format calculation specification?
Look for C as the specification type and then locate the operation-code area.
Read the operation first, its factors or expression and result second, and its conditions or indicators last.
Preserve the columns while inspecting the source.
What replaced C-specs in fully free-form RPGLE?
There is no single replacement construct.
Assignments, expressions, structured operations, built-in functions, procedure calls, and I/O statements collectively express the responsibilities that appeared in traditional calculation specifications.
Is EVAL required for assignment in free-form RPGLE?
Usually not.
You can normally write target = expression; when no EVAL extender is needed and the target name does not conflict with a supported operation-code name.4
What is the difference between DOW and DOU?
DOW repeats while its condition is true and may run zero times.
DOU repeats until its condition becomes true and processes its group at least once.7
Should new RPGLE use EXSR subroutines or procedures?
Learn EXSR, BEGSR, and ENDSR so you can maintain existing code.
For new modular logic, prefer clearly named procedures and prototyped calls because their inputs, outputs, and compiler-checked interfaces can be made explicit.11
Key Takeaways
- Traditional C-specs expressed the executable calculations and business logic of RPG programs.
- Their fixed fields help you recognize operations, operands, results, conditions, and indicators in legacy source.
- Operation codes are verbs; classify the responsibility before studying syntax details.
- Modern fully free-form RPGLE keeps the same responsibilities but expresses them through readable statements, expressions, built-in functions, and calls.
- Arithmetic and structured logic often map cleanly, while movement, indicator, call, and subroutine patterns require behavioral analysis.
- C-specs are primarily legacy-reading knowledge. New RPGLE should generally use fully free-form syntax.
- A safe modernization identifies intent, maps syntax, and verifies preserved behavior.
Continue Your Learning
- Previous: RPGLE Input and Output Specifications Explained
- Current: RPGLE Calculation Specs and Logic Blocks
- Next: RPGLE Indicators and Status Flags (ARTICLE-057, planned in the canonical RPGLE cluster)
- Later: RPGLE Source Layout and Readability (ARTICLE-058, planned)
- Return to: RPGLE for Beginners: A Practical IBM i Learning Path

The next lesson examines indicators and status flags because legacy calculation lines often use them to carry conditions between operations.
That lesson keeps indicators visible for maintenance without making them the center of new RPGLE design.
IBM Evidence Used
This lesson uses IBM’s ILE RPG documentation as its technical evidence:
- IBM’s specification references define the purpose, order, and traditional layout of calculation specifications.1 2 3
- IBM’s free-form and operation references support the assignment, arithmetic, movement, structured-flow, and array mappings used in the examples.4 5 6 7 8
- IBM’s indicator, subroutine, and call references support the legacy-maintenance cautions and modern modular direction.9 10 11
References
- Calculation Specifications — IBM
- RPG IV Specification Types — IBM
- Traditional Syntax — IBM
- Arithmetic Operations — IBM
- Move Operations — IBM
- Free-Form Statements — IBM
- Structured Programming Operations — IBM
- Resulting Indicators — IBM
- Array Operations — IBM
- Subroutine Operations — IBM
- Call Operations — IBM