Variable with usage COMP in COBOL - cobol

I am trying to understand how the COBOL variables with COMP Usage clause stores values.
I tried one example as below
01 VAR14 PIC S9(5) USAGE COMP.
MOVE 12345 TO VAR14
DISPLAY VAR14
In SPOOL the value of VAR14 is coming as 0000012345.
S9(5) COMP size is 4 bytes as per manuals so my understanding is VAR14 should be displayed as 000012345.
The binary representation as below:
0000 0000 0000 0000 0011 0000 0011 0100‬
Can someone please help in understanding the output value 0000012345 ?
Thanks

In IBM's Enterprise COBOL, there are four ways to define a binary field: COMP; COMP-4; BINARY; COMP-5.
How does that come about? A COMPUTATIONAL field (COMP for short, and here short for "all COMPUTATIONAL fields") is "implementor defined". Which means what is COMP-something in one compiler, may be COMP-somethingelse in another compiler, or may even have no direct equivalent.
And yes, you can code COMPUTATIONAL, COMPUTATIONAL-4 and COMPUTATIONAL-5 if you want. The compiler will be happy.
To standardise things, the 1985 COBOL Standard introduced BINARY and PACKED-DECIMAL as USAGEs. For portability to other COBOL compilers, these would be the best USAGEs for COMP and COMP-3 (packed-decimal) fields.
What is the difference between these different binary fields? Mostly, none. COMP, COMP-4 and BINARY are in fact synonyms of each other in the compiler (more accurately, COMP-4 and BINARY are synonyms of COMP).
COMP-5, also known as "native binary", is different. COBOL has what you might call "decimal-binary" fields (COMP and siblings). That is, the data is stored as binary but its maximum and minimum values are the number and full value of the PICture clause which is used in the definition.
COMP PIC 9 - can contain zero to nine.
COMP PIC S99 - (signed) can contain -99 to +99.
COMP PIC 999 - can contain zero to 999.
COMP-5 is different.
COMP PIC 9 - can contain zero to 65535.
COMP PIC S99 - (signed) can contain -32768 to +32767.
COMP PIC 999 - can contain zero to 65535.
What happens for COMP-5 is that the PICture is used to define the size of the field (as with other binary fields) but every possible bit-value is valid.
How does the PICture relate to the size of the definition? PIC 9 through PIC 9(4) will be stored in a half-word-sized field (which is two bytes). PIC 9(5) through PIC 9(9) will be stored in a word-sized field (which is four bytes). PIC 9(10) through PIC 9(18) will be stored in a double-word-sized field (eight bytes).
OK, so how does this difference (COMP-5 use all the bits, COMP can only represent the decimal value of the PICture) affect what is defined? Doesn't "native binary" sound much better, and obviously faster, than anything "non-native" would give?
The difference is in how they truncate. And, as scintillating as "native binary" sounds, it is generally slower than using COMP & CO, because of the truncation.
COMP truncates to the decimal value of the PICture. COMP-5 truncates to the size of the field.
Consider (names just for demonstration, only ever use descriptive names):
01 PROGA COMP PIC 9(4).
01 PROGB COMP-5 PIC 9(5).
01 PROGC BINARY PIC 9(4) VALUE 9999.
ADD PROGC TO PROGA
ADD PROGC TO PROGB
Remembering that PROGA has a maximum value of 9999, and noting that 19998 fits easily within the existing size of the field, the compiler can effect the addition and then truncate to the decimal value, all in-place.
Remembering that PROGB has a maximum value of 65535 and there is absolutely fat chance that there is enough room in the original field to successfully add a further 65535, the compiler has to generate a temporary field of double the original size, do the addition, and then truncate back to the original maximum value, getting that result back to the original field.
ADD 1 TO PROGA
ADD 1 TO PROGB
Note that with these two, ADD 1 TO PROGA, since it is less than 9999, will still allow the ADD to be done in place (obviously) but ADD 1 TO PROGB will still require the expansion of the field and all that mucking-about, because PROGB just may have a value of 65535 in it already, so the compiler has to allow for that.
Coming to DISPLAY. You have COMP PIC S9(5), and you get a 10-digit output. Why? OK, size you have worked out, the field is four bytes long. However, that should get you a five-digit output, in the range -99999 to +99999. Let's pretend for a moment that your field was instead COMP-5 PIC S9(5).
With COMP-5 you all the bits are valid, and, for a signed field, your range for a full-word/word is -2,147,483,648 through +2,147,483,647. That's 10 digits, note. Which matches to the 10 digits you got in your output. What happened?
Compiler option TRUNC. If you use compiler option TRUNC(BIN), all your COMP/COMP-4/BINARY fields are treated as COMP-5. End of story. You have TRUNC(BIN) either specifically chosen by you, your project, or as your site default. This is not necessarily a good choice.
Other values of compiler option TRUNC are STD, which does the "normal" truncation for COMP/COMP-4/BINARY, and OPT which does whatever is best (for performance) at the time.
Note, strongly not, that TRUNC(OPT) imposes a contract on the programmer. "I will not, must not, and will never even consider, allow a COMP/COMP-4/BINARY field to have a value which does not conform to it's PICture. If I do, it is all my fault, full-stop, end-of-story, and no crying from me".
Don't, except for the purposes of investigating how things work, ever just up and change a TRUNC setting. If you do, you can break things, and it can be a very, very subtle break.
My advice: TRUNC(BIN), don't use it unless you have to (someone decided, and you have no choice); TRUNC(STD) use if your site is scared of the contract; TRUNC(OPT) use if your site is comfortable with the contract.
Do use COMP-5, for individual field-definitions, where you need to. Where do you need to? For any place you have a binary field whose range is beyond the "decimal value" of its PICture. For instance, look to the size of the CICS COMMAREA and the field which indicates how big an individual example is. Look to a VARCHAR host-field in a COBOL program. Data communicating with JAVA or C/C++ may be like that. Otherwise, for new programs, prefer BINARY, which shows that you are slap-up-to-date with 1985.
Setting TRUNC for investigative purposes.
CBL TRUNC(STD)
ID (or IDENTIFICATION) DIVISION.
Compiler options can also be set by the PARM statement in the JCL for the compile, but you may not have access to that. CBL will override any value set in the PARM. There is an installation option which can prevent the use of CBL (also known as PROCESS). Individual options can also be "fixed" at installation time. If your site has fixed TRUNC or prevented CBL, you won't be able to try these things out.

COMP usage clause will be called as BINARY or COMPUTATION.
COMP usage clause applicable to Numeric data type only.
COMP usage is a binary representation of data.
The data in COMP variables stored memory in pure binary format.
The memory allocation for COMP USAGE is like below.
Picture Number of Bytes
S9 to S9(4) 2
S9(5) to S9(9) 4
S9(9) to S9(18) 8

Related

Decimals in COBOL

I'm very new to COBOL. I'm following the tutorials that came with Micro Focus and I can't seem to get the example to work right. I'm trying to print -123.45 and I keep getting the following,
I looked up a number of posts on here and they don't address my problem. I'm using Micro Focus' Visual COBOL in Eclipse. Here's my code,
program-id. tictac as "tictac".
environment division.
configuration section.
data division.
working-storage section.
01 WS-NUM3 PIC S9(3)V9(2) VALUE -123.45.
procedure division.
Display WS-NUM3.
goback.
end program tictac.
The V in your picture clause is an implied decimal point. I think you want a field with PIC -999.99, where the . is an explicit decimal point, for its picture clause.
You might think of this as COBOL making a distinction between how a variable is defined and how it is shown. Sort of like a format string in printf is just specifying how to show a variable, not how it is defined. Though in both cases the definition and how it is shown have to match up to a certain extent.
Choosing the right picture clause for a numeric field is important; if you're doing calculations it can have a significant performance impact.
So it's common to have a field with a definition such as...
PIC 9(4)V99 COMP-3
...and a corresponding field for output purposes such as...
PIC ZZZ9.99
...so that computations can be done on the first, and when displaying the field is necessary one uses a MOVE statement to copy the contents of the first to the second.

RULES(NOEVENPACK) in Enterprise COBOL. Why we need to check if packed-decimal is not in even digits?

I am reading the following statement and I am not sure why we must have the packed-decimal in odd digits? Is the following statement true, that you can only have odd number of digits in hardware? Can you give me a example to show why it says that?
RULES(NOEVENPACK) This compiler option will tell you if you
accidentally define a Pack Decimal data item within even number of
digits. You can only have odd number of digits in hardware. If you
have one byte you have one digit , 2 byte you have 3 digit, 3 byte
-->5 digit.
In a packed-decimal field, the right-most half-byte (nybble) is the sign position. Each other half-byte in the field is a digit, 0-9.
This means that the storage occupied by a packed-decimal field represents an odd number of digits. You have no choice over that.
If you define PACKED-DECIMAL PIC 9(4) you get
?NNNNS
Where N is a digit (see, there are four of them) and S is the sign (since the field is defined as unsigned, it will have a sign of F, which is always treated as positive).
What about that ?. It can't not be there. Since it can't not be there, the compiler has to generate code so that it can only contain a zero, which won't affect the value of the field.
If you define PACKED-DECIMAL PIC 9(5) you get
NNNNNS
Five digits, sign, and nothing else for the compiler to worry about. No code generated beyond what is otherwise required for the field.
So your code runs faster.
You may wonder "how much does that matter?". If you consider how many packed-decimal fields you may see in a program, if each of those, every time it was referenced, had code to make the first digit zero, you've got quite a lot of code, for every pass through the program.
On the Mainframe you, generally, pay for resource-usage. If you avoid that in 5,000 programs which are processing 10,000,000 transactions a day, 365 days a year, then it adds up.

Different results using OCCURS with different compilers

I'm attempting to output the following row using DISPLAY and am getting the correct result in Micro Focus COBOL in Visual Studio and the Tutorialspoint COBOL compiler, but something strange when running it on a z/OS Mainframe using IBM's Enterprise COBOL:
01 W05-OUTPUT-ROW.
05 W05-OFFICE-NAME PIC X(13).
05 W05-BENEFIT-ROW OCCURS 5 TIMES.
10 PIC X(2) VALUE SPACES.
10 W05-B-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS.
05 PIC X(2) VALUE SPACES.
05 W05-OFFICE-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS.
It appears in Enterprise COBOL that the spaces are being ignored, and is adding an extra zero-filled column even though the PERFORM VARYING and DISPLAY code is the exact same in both versions:
PERFORM VARYING W02-O-IDX FROM 1 BY 1
UNTIL W02-O-IDX > W12-OFFICE-COUNT
MOVE W02-OFFICE-NAME(W02-O-IDX) TO W05-OFFICE-NAME
PERFORM 310-CALC-TOTALS VARYING W02-B-IDX FROM 1 BY 1
UNTIL W02-B-IDX > W13-BENEFIT-COUNT
MOVE W02-O-TOTAL(W02-O-IDX) TO W05-OFFICE-TOTAL
DISPLAY W05-OUTPUT-ROW
END-PERFORM
W13-BENEFIT-COUNT is 5 and never changes in the program, so the 6th column is a mystery to me.
Correct output:
Strange output:
Edit: as requested, here is W02-OFFICE-TABLE:
01 W02-OFFICE-TABLE.
05 W02-OFFICE-ROW OCCURS 11 TIMES
ASCENDING KEY IS W02-OFFICE-NAME
INDEXED BY W02-O-IDX.
10 W02-OFFICE-CODE PIC X(6).
10 W02-OFFICE-NAME PIC X(13).
10 W02-BENEFIT-ROW OCCURS 5 TIMES
INDEXED BY W02-B-IDX.
15 W02-B-CODE PIC 9(1).
15 W02-B-TOTAL PIC 9(5)V99 VALUE ZERO.
10 W02-O-TOTAL PIC 9(5)V99 VALUE ZERO.
and W12-OFFICE-COUNT is always 11, never changes:
01 W12-OFFICE-COUNT PIC 99 VALUE 11.
The question is not so much "why does Enterprise COBOL do that?", because it is documented, as "why do those other two compilers generate programs that do what I want?", which is probably also documented.
Here's a quote from the draft of what became the 2014 COBOL Standard (the actual Standard costs money):
C.3.4.1 Subscripting using index-names
In order to facilitate such operations as table searching and
manipulating specific items, a technique called indexing is available.
To use this technique, the programmer assigns one or more index-names
to an item whose data description entry contains an OCCURS clause. An
index associated with an index-name acts as a subscript, and its value
corresponds to an occurrence number for the item to which the
index-name is associated.
The INDEXED BY phrase, by which the index-name is identified and
associated with its table, is an optional part of the OCCURS clause.
There is no separate entry to describe the index associated with
index-name since its definition is completely hardware oriented. At
runtime the contents of the index correspond to an occurrence number
for that specific dimension of the table with which the index is
associated; however, the manner of correspondence is determined by the
implementor. The initial value of an index at runtime is undefined,
and the index shall be initialized before use. The initial value of an
index is assigned with the PERFORM statement with the VARYING phrase,
the SEARCH statement with the ALL phrase, or the SET statement.
[...]
An index-name may be used to reference only the table to which it is
associated via the INDEXED BY phrase.
From the second paragraph, it is clear that how an index is implemented is down to the implementor of the compiler. Which means that what an index actually contains, and how it is manipulated internally, can vary from compiler to compiler, as long as the results are the same.
The last paragraph quoted indicates that, by the Standard, a specific index can only be used for the table which defines that specific index.
You have some code equivalent to this in 310-CALC-TOTALS: take a source data-item using the index from its table, and use that index from the "wrong" table to store a value derived from that in a different table.
This breaks the "An index-name may be used to reference only the table to which it is associated via the INDEXED BY phrase."
So you changed your code in 310-CALC-TOTALS to: take a source data-item using the index from its table, and use a data-name or index defined on the destination table to store a value derived from that in a different table.
So your code now works, and will give you the same result with each compiler.
Why did the Enterprise COBOL code compile, if the Standard (and this was the same for prior Standards) forbids that use?
IBM has a Language Extension. In fact two Extensions, which are applicable to your case (quoted from the Enterprise COBOL Language Reference in Appendix A):
Indexing and subscripting ... Referencing a table with an index-name
defined for a different table
and
OCCURS ... Reference to a table through indexing when no INDEXED BY
phrase is specified
Thus you get no compile error, as using an index from a different table and using an index when no index is defined on the table are both OK.
So, what does it do, when you use another index? Again from the Language Reference, this time on Subscripting using index-names (indexing)
An index-name can be used to reference any table. However, the element
length of the table being referenced and of the table that the
index-name is associated with should match. Otherwise, the reference
will not be to the same table element in each table, and you might get
runtime errors.
Which is exactly what happened to you. The difference in lengths of the items in the OCCURS is down to the "insertion editing" symbols in your PICture for the table you DISPLAY from. If the items in the two tables were the same length, you'd not have noticed a problem.
You gave a VALUE clause for your table items (unnecessary, as you would always put something in them before the are output) and this left your "sixth" column, the five previous columns were written as shorter items. Note the confusion caused when the editing is done to one length and the storing done with a different implicit length, you even overwrite the second decimal place.
IBM's implementation of INDEXED BY means that the length of the item(s) being indexed is intrinsic. Hence the unexpected results when the fields referenced are actually different lengths.
What about the other two compilers? You'd need to hit their documentation to be certain of what was happening (something as simple as the index being represented by an entry-number (so plain 1, 2, 3, etc), and the allowing of an index to reference another table would be enough). There should be two extensions: to allow an index to be used on a table which did not define that index; to allow an index to be used on a table where no index is defined. The two logically come as a pair, and both only need to be specific (the first would do otherwise) because the are specifically against the Standard.
Micro Focus do have a Language Extension whereby an index from one table may be used to reference data from another table. It is not explicit that this includes referencing a table with no indexes defined, but this is obviously so.
Tutorialspoint uses OpenCOBOL 1.1. OpenCOBOL is now GnuCOBOL. GnuCOBOL 1.1 is the current release, which is different and more up-to-date than OpenCOBOL 1.1. GnuCOBOL 2.0 is coming soon. I contribute to the discussion area for GnuCOBOL at SourceForge.Net and have raised the issue there. Simon Sobisch of the GnuCOBOL project has previously approached Ideaone and Tuturialspoint about their use of the out-dated OpenCOBOL 1.1. Ideaone have provided positive feedback, Tutorialspoint, who Simon has again contacted today, nothing yet.
As a side-issue, it looks like you are using SEARCH ALL to do a binary-search of your table. For "small" tables, it is likely that the overhead of the mechanics of the generalised binary-search provided by SEARCH ALL outweighs any expected savings in machine resources. If you were to be processing large amounts of data, it is likely that a plain SEARCH would be more efficient than the SEARCH ALL.
How small is "small" depends on your data. Five is likely to be small close to 100% of the time.
Better performance than SEARCH and SEARCH ALL functionality can be achieved by coding, but remember that SEARCH and SEARCH ALL don't make mistakes.
However, especially with SEARCH ALL, mistakes by the programmer are easy. If the data is out of sequence, SEARCH ALL will not operate correctly. Defining more data than is populated gets a table quickly out of sequence as well. If using SEARCH ALL with a variable number of items, consider using OCCURS DEPENDING ON for the table, or "padding" unused trailing entries with a value beyond the maximum key-value that can exist.
I'd be very hesitant about mixing VALUE with OCCURS and re-code the WS as
01 W05-OUTPUT-ROW.
05 W05-OFFICE-NAME PIC X(13).
05 W05-BENEFITS PIC X(55) VALUE SPACES.
05 FILLER REDEFINES W05-BENEFITS.
07 W05-BENEFIT-ROW OCCURS 5 TIMES.
10 FILLER PIC X(02).
10 W05-B-TOTAL PIC ZZ,ZZ9.99.
05 FILLER PIC X(02) VALUE SPACES.
05 W05-OFFICE-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS.
Perhaps it has something to do with the missing fieldname?
Ah! evil INDEXED. I'd make both ***-IDX variables simple 99s.

Redefining an array as a string works in MFCOBOL but warns in GnuCOBOL

01 COUNTER.
03 DIGITS1 OCCURS 40 TIMES PIC 9.
03 STRING1 REDEFINES DIGITS1 pic X(40).
That compiles fine in Micro Focus Visual COBOL 2.3 in Visual Studio 2015. It gives an error in GnuCOBOL, viz
The original definition should not have OCCURS
Why the difference and what do I do to have an array of digits that can also be viewed as a string of digits?
It is either a COBOL Language Extension in Micro Focus Visual COBOL 2.3, or it is a bug there.
Indeed, locating some Micro Focus documentation reveals:
OSVS MF The data description for data-name-2 can contain an OCCURS
clause.
OSVS and MF indicate what the Language Extension relates to. MF is Micro Focus, OSVS I assume is for OS/VS COBOL on an IBM Mainframe. I used that a lot, but since I don't code like that I can't say whether it worked like that. OS/VS COBOL was to the 1974 Standard.
Locating an old (1975) manual for OS/VS COBOL, here is the defintion of REDEFINES:
level number data-name-l REDEFINES data-name-2
That also serves for the Micro Focus quote.
Here is the relevant part from that OS/VS COBOL manual:
The data description entry far data-name-2 cannot contain an OCCURS
clause
So I'm not so sure that OSVS in the Micro Focus document is OS/VS COBOL. I know the icons are listed somewhere...
From a draft of the 2015 Standard (it is expensive to obtain the actual Standard):
The data description entry for data-name-2 shall not contain an OCCURS
clause. However, data-name-2 may be subordinate to an item whose data
description entry contains an OCCURS clause. In this case, the
reference to data-name-2 in the REDEFINES clause shall not be
subscripted. Neither the original definition nor the redefinition
shall include an occurs-depending table.
The 1985 Standard as it relates to the REDEFINES of an OCCURS is the same.
This should do for you:
01 COUNTER.
03 DIGITS1 OCCURS 40 TIMES PIC 9.
Just use COUNTER instead of STRING1 (I hope those names are just for this example, not the real ones).
COUNTER is a group item, which is treated as an alpha-numeric item with a total length equal to the sum of the lengths of all its subordinate items.
You want STRING1 to be a 40-byte PIC X field, when you already have one: COUNTER.
I always code my tables like this:
01 FILLER.
05 FILLER PIC something.
05 FILLER.
10 FILLER OCCURS 40 TIMES.
15 FILLER PIC something.
05 FILLER PIC something.
OK, conceptually I do that. Then, for each level of an OCCURS that I actually require, I give it a name. If there are items outside the OCCURS structure I don't need, I delete them.
With this, if you need to REDEFINES the group which contains the OCCURS, no problem. If you need to REDEFINES the OCCURing item, no problem. You can't REDEFINES (or do much useful) with the item actually containing the OCCURS, so it remains a FILLER.
This is for "maintainability". The next person along will never have to alter the structure of the OCCURS, so never have to worry when making a change. With the short-hand structure, a future change may require a reorganisation, which then has to be considered for impact.
If your table had been coded that way, there would not have been a problem anyway.
Consult your Micro Focus documentation for the REDEFINES, they usually indicate Language Extensions directly there. If there is not a Language Extension that you can locate, raise an issue with Micro Focus. They will point you to the documentation of the Extension, or do something else constructive with it.
Micro Focus the company has consumed some "small system" commercial compilers, and provides a lot of support to allow a migration path from those compilers to straight Micro Focus ones. My guess would be that you'll find a Language Extension linked to that.
Incidentally, it is also non-Standard to be able to REDEFINES a smaller item as a larger item. DIGITS1 has a length of one. Your REDEFINES item a length of 40. However, the Micro Focus REDEFINES is allowing you to redefine the entire length of the OCCURS.
By error, do you mean the warning?
identification division.
program-id. redef.
data division.
working-storage section.
01 COUNTER.
03 DIGITS1 OCCURS 40 TIMES PIC 9.
03 STRING1 REDEFINES DIGITS1 pic X(40).
procedure division.
move 1 to DIGITS1(2)
display ":" STRING1 ":"
goback.
end program redef.
with
prompt$ cobc -xj redef.cob
redef.cob: 8: Warning: The original definition 'DIGITS1' should not have OCCURS
:0100000000000000000000000000000000000000:
prompt$ cobc --version
cobc (GNU Cobol) 2.0.0
Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Keisuke Nishida
Copyright (C) 2006-2012 Roger While
Copyright (C) 2009,2010,2012,2014,2015 Simon Sobisch
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Built Nov 02 2015 05:58:19
Packaged Oct 25 2015 21:40:28 UTC
C version "4.9.2 20150212 (Red Hat 4.9.2-6)"
So, that's GnuCOBOL 2.0.
prompt$ cobc -x redef.cob
redef.cob:8: Warning: The original definition 'DIGITS1' should not have OCCURS
prompt$ cobc --version
cobc (GNU Cobol) 1.1.0
...
prompt$ ./redef
:0100000000000000000000000000000000000000:
Looks like it works with 1.1 as well.
I can't get rid of the warning though.

Why is this causing an error in Cobol?

Why would this if statement below need a NEXT SENTENCE because there is a statement in both the IF and the ELSE part of the statement.
Question: Why is this an error in the if statement.
CHECK-PARM.
IF NAME = 'SW89JS' THEN 1183
E-NAME = 'FALSE'
Expected a verb or "NEXT SENTENCE", but found "E-NAME". The statement was discarded.
ELSE
E-NAME = 'TRUE'
"E-NAME" was invalid. Skipped to the next verb, period or procedure-name definition.
P-NAME = 'SW89JS'
END-IF.
Since it is somewhere buried in this answer, I'm going to repeat it up hear, even expand it a little.
You have a value you are testing. From the name it likely comes from the PARM on the EXEC card in the JCL.
You test the value, set a flag (TRUE/FALSE literals) on the result of the value, and use it later.
With an 88 you can make that parm value into the flag itself.
01 NAME PIC X(6).
88 IT-IS-SW89JS VALUE "SW89JS".
Now you can never get your flags out of step, as you only have one flag. One fewer flag to understand and potentially get wrong.
Because we don't have assignments in COBOL.
MOVE 'TRUE' TO E-NAME
or
MOVE data-name-with-value-true TO E-NAME
or
01 FILLER PIC X VALUE SPACE.
88 IT-IS-SW89JS VALUE "Y".
SET IT-IS-SW89JS TO TRUE
or
01 NAME PIC X(6).
88 IT-IS-SW89JS VALUE "SW89JS".
And with the last forget about anything else.
COBOL is not like many other languages. No strings, as you may know them. No arrays, as you may know them. No assignments. No booleans. No user-written functions. Few Intrinsic Functions. No public function libraries. It does have some other stuff :-)
A couple of points from the comments.
COBOL is a language of fixedness. Fixed-length field, fixed-length tables. The length of the data in a 30-byte field is 30 bytes. The length of the content of the field, in terms of what the data represents, is something the programmer has to work out, if needed. Mostly we don't need it, so we don't have to work it out.
The fixedness also imposes limits. So we think of ways to do things differently, so we don't have a limit, waiting to bust, dangling over our heads. We don't just pick a function which looks like maybe it makes life easy for us (less code to write) regardless of how it carries out the task. Usually we don't have a function anyway, and we write specific code to be re-used, through a CALL, for a specific system or set of systems.
A COBOL program may take longer to write (I say may because 90+% of the time it is a question of starting out by copying a program which is close to what you want, and then making it specific) but that program may have a lifetime of 30 years. It may be changed many times during its life. It may never be changed, but need to be understood many times during that period.
Conceptually, COBOL is a very different language from those with assignments/strings/arrays. If you are supposed to pick up COBOL with no training, there will be many pitfalls.
Yes, Bruce Martin, I suppose COBOL does have an assignment: the COMPUTE. The left-side can only be numeric or numeric-edited, although there can be multiple fields, and the right-side can only have numerics (or intrinsic functions returning numerics). It only supports basic mathematical operators (+, -, , /, *). It does allow rounding of the final answer if desired, and also allows for interception of "overflow" (ON SIZE ERROR).
It can be used as a simple assignment:
COMPUTE A = B
This will generate the same code as:
MOVE B TO A
Some people do this, though I've never really worked out why. There is a rumour that it means you can use ON SIZE ERROR (and don't forget END-COMPUTE if you do use it) to trap an overflow.
However, I always make my fields big enough, or deliberately truncate when that is the result I want, so I don't really get that.
In short, welcome to COBOL. Don't expect it to be like any other language you've used.
As Bill stated the problem is:
E-NAME = 'FALSE'
In Cobol (unlike most other languages), each statement starts with a control word
e.g.
Compute abc = 123
Move 'FALSE' to E-NAME
Perform abc
Call 'xyz'
With Cobol the control word on the far left of a line tells you what the statement is doing.
Also as Bill stated, in Cobol a boolean is normally define using 88 levels:
01 FILLER PIC X VALUE SPACE.
88 IS-ENAME VALUE "Y".
88 ENAME-OFF VALUE "N".
and your code becomes
IF NAME = 'SW89JS' THEN
Set ENAME-OFF to true
ELSE
Set IS-ENAME to true
Move 'SW89JS' to P-NAME
END-IF.

Resources