razor wrote:
> Hi Simon
>
> I think I will try that.
Yes, Micro Focus support would be the best place to go.
>
> These are the Project properties within Netexpress:
>
> %FILENAME COBIDY(%TARGETDIR) WB3 WB CSI ANIM EDITOR(MF2) ENSUITE(3)
> CHANGE-MESSAGE"0837 N 0011 N" /CONSTANT VN(1700) /CONSTANT GOGO(0)
> REMOVE "SELF" DB2(DBMAN=DB2) DB2(BIND=%BASENAME.BND) DB2(DB=HMS1700)
> SPZERO STICKY-LINKAGE OOCTRL(-G+N-P+Q-W);
This is why I don't really use Micro Focus; far too much is NOT "under the
covers"... Having said that, they DO give you the option of working at a
very low level if that is what you want to do.
I'm taking a break from real work for an hour or so and I decided to see if
I can help with some of this... I have annotated comments ([Pete] [/Pete])
which might help you with understanding how it works.
>
> I'm afraid it's not ESQL unfortunately.
>
> The COBOL code is very, very complicated.
"complicated" is, of course, relative. In the code you posted I see nothing
"complicated"...
>It's nothing like any COBOL
> I've maintained in 30 years experience.
That's because you didn't pick up the OO skills you would need for this,
along the way. Never mind, MOST COBOL guys didn't... It was much easier to
pretend that OO was an unnecessary re-invention of structured modular
programming (it isn't...) or to decide it was a fad that would quickly pass.
(The whole world runs on it now...)
>Basically, the program reads
> a list of Sites and for each Site it then reads all location codes
> for THAT Site. In between, the program allocates memory to store
> these location entries.
There, you see, you're not as bad as you think you are... you sussed what it
does pretty well... :-)
> I have actually narrowed down the problem to
> some code that is executed for each Site.
>
> INVOKE OSMEMORY "newtable" USING
> BY VALUE LENGTH OF WS-LOC-KEY
> BY VALUE WS-OBJ-DIALOG
> BY REFERENCE WS-OSMEMORY-ADDRESS
> BY REFERENCE WS-OBJ-SLLIST
> RETURNING WS-OSMEMORY-REPLY.
>
> OSMEMORY.CBL is a class program that starts doing things like:
Yes, it is a Class which, like most Classes, has methods (behaviours).
Sadly, someone (probably a sometime Assembler programmer) has decided to
have a go at doing stuff that really should be left to the OS.
"Why did you decide to write a class that re-invents what the OS already
does very well?"
"Because I can...
(Besides, I really wanted to be a system programmer and they're making me
maintain this bloody boring COBOL so I need to have a bit of fun...)"
>
> METHOD-ID. "newtable".
>
> LOCAL-STORAGE SECTION.
>
> 01 WS-REPLY USAGE LONG.
>
> LINKAGE SECTION.
>
> 01 LK-ENT-SIZE USAGE LONG.
> 01 LK-OBJ-PARENT USAGE OBJECT REFERENCE.
> 01 LK-MEM-POINTER USAGE POINTER.
> 01 LK-OBJ-MEMORY USAGE OBJECT REFERENCE.
> 01 LK-REPLY USAGE LONG.
>
> INVOKE SUPER "new" RETURNING LK-OBJ-MEMORY. [Pete] This is a
> low level constructor that inherits from the base class (SUPER is the
> Class that this Class derives from) and creates a new instance of the
> Class. It returns a pointer to the area of memory where the new instance
> resides. From then on, you can reference LK-OBJ-MEMORY as if it was the
> Class, so you can invoke methods on it and get/set properties for
> it.[/Pete]
>
> INVOKE LK-OBJ-MEMORY "initializetable" USING [Pete] As noted,
> having got an instance of the table it invokes a method to initialize it.
> Note that it returns a return code (LK-REPLY) that states whether the
> initialization was successful or not. If it wasn't, it invokes the
> finalize method to destroy the instance, release the resources and make
> them available for garbage collection.[/Pete]
> BY VALUE LK-ENT-SIZE
> BY VALUE WS-ENT-TABLEMAX
> BY VALUE LK-OBJ-PARENT
> BY REFERENCE LK-MEM-POINTER
> RETURNING LK-REPLY.
>
> IF LK-REPLY NOT = WS-OSCLASS-OK
> INVOKE LK-OBJ-MEMORY "finalize" USING
> BY REFERENCE LK-OBJ-MEMORY
> RETURNING WS-REPLY
> END-IF.
>
> EXIT METHOD.
>
> -----------------------
>
>
> METHOD-ID. "initializetable". [Pete] Don't get sidetracked
> by the details unless you HAVE to. It is enough to know that the
> "initializetable" method initializes the memory claimed by the Class
> instance.[/Pete]
> CALL OSAPI "VirtualAlloc" USING [Pete] Oh, Great! Let's use
> the OS API functions to explicitly manage the memory allocation, now that
> we have set up all the parameters for it...
The system is using "initialize" to allocate memory dynamically and
"initializetable" to create the table it needs in the newly acquired
space.[/Pete]
> BY VALUE 0
> BY VALUE LK-MEM-SIZE
> BY VALUE WS-MEMFLAGS
> BY VALUE WS-MEMREADWRITE
> RETURNING LK-MEM-POINTER.
> IF LK-MEM-POINTER = NULL
> CALL OSAPI "GetLastError" RETURNING WS-LAST-ERROR
> MOVE WS-OSCLASS-FAILED TO LK-REPLY
> EXIT METHOD
> END-IF.
>
> MOVE WS-TYPE-MEMORY TO WS-TYPE.
>
> MOVE LK-MEM-SIZE TO WS-MEM-SIZE.
> SET WS-MEM-POINTER TO LK-MEM-POINTER.
>
> SET WS-OBJ-PARENT TO LK-OBJ-PARENT.
>
> IF WS-OBJ-PARENT NOT = NULL
> INVOKE WS-OBJ-PARENT "register" USING
> BY VALUE SELF
> RETURNING WS-REPLY
> END-IF.
>
> MOVE 0 TO WS-LAST-ERROR.
> MOVE WS-OSCLASS-OK TO LK-REPLY.
>
> EXIT METHOD.
>
> END METHOD "initialize".
[Pete] All of the above is actually quite straightforward to an OO
programmer. (And it isn't badly written...) My criticism would be that there
was no need to do it in the first place, but the author would counter, that,
as COBOL does not provide for dynamic memory and table allocation, there
was... (Really, it is just a lot more "fun" (for some people...) to do
something low-level. And if it is "complicated"... well, that works towards
ensuring job security... :-) )
There are a few fundamentals you need to keep in mind while you are dealing
with this stuff.... ( Due to time/space restrictions I can't give you a
brain dump on OO programming here, but I can give you enough to help you
out) COBOL examples below are a guide and may not work exactly with your
specific COBOL implementation. (I believe they will be close, but I have
neither time nor inclination to check the exact details of NetExpress
syntax...)
1. The structures you are dealing with consist of: "Classes".
Classes can "contain" (actually "implement" is a better word):
1. Methods. (These are the behaviours that the Class can exhibit. They are
like procedures, but there is a little more to it than that because it isn't
just strictly procedural. You can think of Methods as what the Class
"knows"...)
2. Interfaces. (These are portals that the Class provides for communication
with the outside world. A "method signature" (the name of the method plus
any parameters it accepts and returns) is an example of an interface.
Classes are sealed off from the outside world (encapsulated) and can ONLY be
manipulated using their provided interfaces.
3. Properties. (Sometimes called "attributes". These are data fields that
the Class makes public, through an interface which allows you to get and set
them. Sometimes the behaviour of a method can be modified if a certain
property is set before invoking the method.)
4. Events. (These are the events that the Class is interested in and will
respond to. Could be a mouse click or may be nothing at all...)
2. A Class cannot be executed. You cannot even execute its methods or check
its properties. You have to create an INSTANCE of it first. (This is just
like making a copy of it and then doing everything with the copy. ) This is
such a fundamental thing that most classes will either inherit or provide
their own "constructor" method. The constructor creates an instance of the
class and returns to you an address to it. From then on, you reference this
returned address as if it were the Class itself. The returned address is
called an "OBJECT REFERENCE" and an object reference represents an instance
of a Class. The phrase "instance of a Class"can be replaced with "OBJECT".
Sadly, some programmers use these terms loosely and it can lead to
confusion. Classes and objects are intimately related, but they are NOT the
same thing...
3. In most programming languages you reference things by using the object
followed by a dot. ("dog.sit()" would invoke the "sit" METHOD of the "dog"
object. The parentheses tell us this is a method, and would contain
parameters if the sit method required them. "dog.collartype" would return
the "collartype" PROPERTY and tell us whether it was leather or chain or
whatever . In OO COBOL the otherwise standard dot notation is not used.
COBOL qualification is used instead, so the two examples become"
INVOKE dog "sit" USING/RETURNING etc. and... MOVE "collartype" OF "dog"
TO WS-COLLAR... etc. (You could also access the "collartype" property with:
INVOKE dog "GET" using "collartype" RETURNING WS-COLLAR ...)
The above is a very quick look around the ballpark and the most-used
features.
Don't worry too much about things like "instantiation" (creating an instance
of - returns an object reference), "polymorphism" (allowing a method to
have more than one signature by providing different interfaces to the same
method, and the other "Computer Science" stuff.
And don't try to read the details of EVERY method... Understand that methods
are encapsulated. They do what they do; get your head around the function
they perform and visualize them as little LEGO blocks...
It is perfectly safe to take a copy of a method then fiddle with it.
Encapsulation ensures that you can't directly destroy anything up or
downstream. If your change doesn't work then replace the original.
>
> ---------------------------------
>
> Hey, I have 20,000,000 lines of code just like this to maintain on my
> own. :-)
>
> I'm afraid the OO stuff here is so over my head without anybody there
> to ask. All long gone.
>
If you have any further specific questions on OO programming, post them here
and I'll try to respond. (I don't come here so often these days but I'll do
what I can.)
Pete.
--
"I used to write COBOL...now I can do anything."