First the routine.
| IDENTIFICATION DIVISION.
| PROGRAM-ID. rawprint.
| ENVIRONMENT DIVISION.
| CONFIGURATION SECTION.
| SPECIAL-NAMES.
| ENVIRONMENT-NAME IS Environment-Name
| ENVIRONMENT-VALUE IS Environment-Value
| .
| INPUT-OUTPUT SECTION.
| FILE-CONTROL.
| SELECT OPTIONAL Log-File
| ASSIGN Log-Name
| ORGANIZATION LINE SEQUENTIAL
| FILE STATUS File-Status
| .
| DATA DIVISION.
| FILE SECTION.
| FD Log-File.
| 01 Log-Record PIC X(80).
| WORKING-STORAGE SECTION.
| 01 File-Status.
| 03 FS-B1 PIC X.
| 03 FS-B2 PIC X.
| 01 Log-Name PIC X(40).
| 01 SysDate.
| 03 SysYYMM PIC X(4).
| 03 SysDD PIC X(2).
| 01 SysTime.
| 03 SysHH PIC X(2).
| 03 SysMM PIC X(2).
| 03 SysSS PIC X(2).
| 03 Sys00 PIC X(2).
|
| 01 Testing-Only PIC X VALUE SPACE.
| 01 Pid PIC S9(9) COMP-5.
| 01 PidN PIC 9(6).
| 01 ffd PIC S9(4) COMP-5.
| 01 Buffer PIC X(1024).
| 01 file-Flags PIC S9(4) COMP-5.
| 01 file-Mode PIC S9(4) COMP-5.
| 01 write-Count PIC 9(4) COMP-5.
| 01 I PIC S9(4) COMP-5.
| 01 File-Name PIC X(80).
| 01 LP-Option PIC X(40).
| 01 Log-Text PIC X(80).
| LINKAGE SECTION.
| 01 RawPrint-Function.
| 88 RawPrint-Open VALUE "O".
| 88 RawPrint-Close VALUE "X".
| 88 RawPrint-Page VALUE "P".
| 88 RawPrint-Print VALUE "0" THRU "9".
| 03 RawPrint-Lines PIC 9.
| 01 RawPrint-Text PIC X(1024).
| 01 RawPrint-Length PIC S9(4).
| 01 RawPrint-Result PIC X.
|
| PROCEDURE DIVISION USING RawPrint-Function
| RawPrint-Text
| RawPrint-Length
| RawPrint-Result
| .
| Program-RawPrint.
|
| MOVE ZERO TO Program-Status
| MOVE SPACES TO RawPrint-Result
| EVALUATE RawPrint-Function
| WHEN "T" MOVE "Y" TO Testing-Only
| WHEN "O" PERFORM Open-RawFile
| WHEN "X" PERFORM Close-RawFile
| WHEN "P" PERFORM Page-RawFile
| WHEN "0" THRU "9" PERFORM Print-RawFile
| WHEN OTHER MOVE -2 TO Program-Status
| END-EVALUATE
|
| EXIT PROGRAM
| .
|
| Open-RawFile.
|
| CALL "COB_GET_PROCESSID" USING BY REFERENCE Pid
| MOVE ZERO TO ffd
| MOVE SPACES TO file-Name
| IF ( RawPrint-Length = ZERO
| OR RawPrint-Text(1:RawPrint-Length) = SPACES
| )
| MOVE Pid TO PidN
| STRING "PRT"
| PidN
| x"00" DELIMITED BY SIZE
| INTO file-Name
| ELSE
| STRING RawPrint-Text DELIMITED BY SPACE
| x"00" DELIMITED BY SIZE
| INTO file-Name
| END-IF
| MOVE 65 TO file-Flags
| MOVE 384 TO file-Mode
| ADD 48 TO file-Mode
| ADD 4 TO file-Mode
| CALL "open"
| USING BY REFERENCE file-Name
| BY VALUE file-Flags
| BY VALUE file-Mode
| MOVE Program-Status TO ffd
| MOVE ZERO TO Program-Status
|
| IF ( ffd = ZERO )
| MOVE "File open failed" TO Log-Text
| MOVE file-name TO Log-Text(18:)
| PERFORM Write-Log
| MOVE -1 TO Program-Status
| IF ( Testing-Only = "Y" )
| DISPLAY "Failed"
| END-IF
| MOVE "X" TO RawPrint-Result
| END-IF
| .
|
| Close-RawFile.
|
| IF ( ffd = ZERO )
| MOVE -1 TO Program-Status
| MOVE "X" TO RawPrint-Result
| ELSE
| CALL "close"
| USING BY VALUE ffd
| MOVE ZERO TO ffd
|
| DISPLAY "CBR_LP_OPTION" UPON Environment-Name
| ACCEPT LP-Option FROM Environment-Value
| ON EXCEPTION MOVE SPACES TO LP-Option
| END-ACCEPT
| PERFORM
| VARYING I FROM LENGTH OF LP-Option BY -1
| UNTIL I < 1
| OR LP-Option(I:1) NOT = SPACE
| MOVE x"00" TO LP-Option(I:1)
| END-PERFORM
|
| MOVE SPACES TO buffer
| STRING "lpr " DELIMITED BY SIZE
| LP-Option DELIMITED BY x"00"
| " -r " DELIMITED BY SIZE
| file-Name DELIMITED BY x"00"
| x"00" DELIMITED BY SIZE
| INTO buffer
| MOVE "system:" TO Log-Text
| MOVE buffer TO Log-Text(9:)
| PERFORM Write-Log
| IF ( Testing-Only = "Y" )
| DISPLAY buffer(1:70)
| ELSE
| CALL "system" USING buffer
| END-IF
| END-IF
| MOVE SPACE TO Testing-Only
| .
|
| Page-RawFile.
|
| PERFORM DeBuffer
| ADD 1 TO write-count
| MOVE x"0C" TO buffer(write-count:1)
| PERFORM RaWrite
| .
|
| Print-RawFile.
|
| PERFORM DeBuffer
| PERFORM
| VARYING I FROM 1 BY 1
| UNTIL I > RawPrint-Lines
| ADD 1 TO write-count
| MOVE x"0A" TO buffer(write-count:1)
| END-PERFORM
| PERFORM RaWrite
| .
|
| RaWrite.
|
| IF ( ffd = ZERO )
| MOVE -1 TO Program-Status
| MOVE "X" TO RawPrint-Result
| ELSE
| CALL "write" USING BY VALUE ffd
| BY REFERENCE buffer
| BY VALUE write-count
| END-IF
| .
|
| DeBuffer.
| MOVE RawPrint-Text TO buffer
| MOVE RawPrint-Length TO write-count
| PERFORM
| VARYING write-count FROM RawPrint-Length BY -1
| UNTIL write-count < 1
| OR buffer(write-count:1) NOT = SPACE
| CONTINUE
| END-PERFORM
| ADD 1 TO write-count
| MOVE x"0D" TO buffer(write-count:1)
| .
|
| Write-Log.
|
| ACCEPT SysDate FROM DATE
| ACCEPT SysTime FROM TIME
|
| MOVE SPACES TO Log-Name
| STRING "rawp" SysYYMM ".log"
| DELIMITED BY SIZE
| INTO Log-Name
| OPEN EXTEND Log-File
| IF ( File-Status = "35" )
| OPEN OUTPUT Log-File
| END-IF
| IF ( FS-B1 = ZERO )
| MOVE SPACES TO Log-Record
| STRING SysDD " " SysHH ":" SysMM " "
| Log-Text
| DELIMITED BY SIZE
| INTO Log-Record
| WRITE Log-Record
| CLOSE Log-File
| END-IF
| .
|
| END PROGRAM rawprint.
| *
----------------------------------------------------------------
| * Copyright Azonic Associates and C.Scott Services 2004
| *
----------------------------------------------------------------
| IDENTIFICATION DIVISION.
| Class-Id. RawPrint inherits FjBase.
|
| *<title>
| * RawPrint class
| *<html>
| * Fujitsu Cobol for Linux uses a PostScript printing
| * system that precludes using PCL or other control
| * codes to control the printer directly.
| *
| * The RawPrint class bypasses the standard print system
| * and invokes its own.
| *
| *<pre>
| * Data items:
| *
| * 01 objectref USAGE OBJECT REFERENCE RawPrint.
| * 01 function PIC X.
| * 01 name PIC X(80).
| * 01 text PIC X(1024).
| *
| * Methods:
| *
| * Constructors:
| * -------------
| * INVOKE RawPrint "CreateUnNamed" RETURNING objectref
| *
| * creates a temporay text file and genertes a name.
| *
| * INVOKE RawPrint "CreateNamed" USING name RETURNING objectref
| *
| * creates a temporary text file with the specified name.
| *
| * Object Methods:
| * ---------------
| * INVOKE Invoice "writeLine" USING function text
| *
| * function indicates the line spacing required
| * after the text and should be one of:
| * 0 - 9 : indicates number of lines to space
| * P : indicates a page throw
| *
| * text is a line of text of any length
| *
| * INVOKE Invoice "closePrint"
| *
| * Closes the temporary text file and uses lpr
| * to send it to the required printer.
| *
| * The printer and any other options should be
| * set in the environment variable CBR_LP_OPTION.
| * If this is not specified then the default printer
| * is used.
| *
| *</pre>
| *</html>
|
| ENVIRONMENT DIVISION.
| CONFIGURATION SECTION.
| SPECIAL-NAMES.
| ENVIRONMENT-NAME IS Environment-Name
| ENVIRONMENT-VALUE IS Environment-Value
| .
| Repository.
| Class FjBase.
|
| *
----------------------------------------------------------------
| IDENTIFICATION DIVISION.
| Factory.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
| 01 nSequence PIC 9(4) VALUE ZERO.
| PROCEDURE DIVISION.
|
| IDENTIFICATION DIVISION.
| Method-Id. CreateNamed.
| DATA DIVISION.
| LINKAGE SECTION.
| 01 in-fileName PIC X ANY LENGTH.
| 01 PrintObject usage object reference Self.
| PROCEDURE DIVISION USING in-fileName RETURNING PrintObject.
| Invoke self "NEW"
| returning PrintObject
|
| ADD 1 TO nSequence
| Invoke PrintObject "OPENRAWFILE"
| using in-fileName nSequence
| .
| End Method CreateNamed.
|
| IDENTIFICATION DIVISION.
| Method-Id. CreateUnNamed.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
| 01 blank-fileName pic x(80).
| LINKAGE SECTION.
| 01 PrintObject usage object reference Self.
| PROCEDURE DIVISION RETURNING PrintObject.
| Invoke self "NEW"
| returning PrintObject
|
| MOVE SPACES TO blank-fileName
| ADD 1 TO nSequence
| Invoke PrintObject "OPENRAWFILE"
| using blank-fileName nSequence
| .
| End Method CreateUnNamed.
| End Factory.
|
| *
----------------------------------------------------------------
| IDENTIFICATION DIVISION.
| Object.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
| 01 Testing-Only PIC X VALUE SPACE.
| 01 ffd PIC S9(4) COMP-5.
| 01 fileName PIC X(128).
| 01 lineCount PIC S9(4) VALUE ZERO.
| PROCEDURE DIVISION.
|
| *
----------------------------------------------------------------
| IDENTIFICATION DIVISION.
| Method-Id. writeLine.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
| 01 write-Count PIC 9(4) COMP-5.
| 01 text-length PIC 9(4) COMP-5.
| 01 I PIC S9(4) COMP-5.
| 01 Buffer PIC X(1024).
| LINKAGE SECTION.
| 01 Link-Before.
| 03 Link-Lines PIC 9.
| 01 Link-Text PIC X ANY LENGTH.
| PROCEDURE DIVISION USING Link-Before Link-Text.
|
| MOVE Link-Text TO buffer
| COMPUTE text-length = FUNCTION LENGTH(Link-Text)
| PERFORM
| VARYING write-count FROM text-length BY -1
| UNTIL write-count < 1
| OR buffer(write-count:1) NOT = SPACE
| CONTINUE
| END-PERFORM
| ADD 1 TO write-count
| MOVE x"0D" TO buffer(write-count:1)
|
| IF ( Link-Before = "P" )
| ADD 1 TO write-count
| MOVE x"0C" TO buffer(write-count:1)
| ELSE
| PERFORM
| VARYING I FROM 1 BY 1
| UNTIL I > Link-Lines
| ADD 1 TO write-count
| MOVE x"0A" TO buffer(write-count:1)
| END-PERFORM
| END-IF
|
| IF ( ffd = ZERO )
| CONTINUE
| ELSE
| CALL "write" USING BY VALUE ffd
| BY REFERENCE buffer
| BY VALUE write-count
| END-IF
| .
| End Method writeLine.
|
| *
----------------------------------------------------------------
| IDENTIFICATION DIVISION.
| Method-Id. openRawFile.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
| 01 Pid PIC S9(9) COMP-5.
| 01 PidN PIC 9(6).
| 01 file-Flags PIC S9(4) COMP-5.
| 01 file-Mode PIC S9(4) COMP-5.
|
| LINKAGE SECTION.
| 01 in-fileName PIC X ANY LENGTH.
| 01 nSequence PIC 9(4).
| PROCEDURE DIVISION USING in-fileName nSequence.
|
| MOVE ZERO TO ffd
| IF ( in-fileName(1:1) = SPACE )
| MOVE SPACES TO fileName
| CALL "COB_GET_PROCESSID" USING BY REFERENCE Pid
| MOVE Pid TO PidN
| STRING "PRT"
| PidN
| nSequence
| x"00" DELIMITED BY SIZE
| INTO fileName
| ELSE
| MOVE SPACES TO fileName
| STRING "PRX"
| in-fileName DELIMITED BY SPACE
| x"00" DELIMITED BY SIZE
| INTO fileName
| END-IF
| MOVE 65 TO file-Flags
| MOVE 384 TO file-Mode
| ADD 48 TO file-Mode
| ADD 4 TO file-Mode
| IF ( Testing-Only = "Y" )
| DISPLAY "Opening " fileName(1:60)
| END-IF
| CALL "unlink"
| USING BY REFERENCE fileName
| CALL "open"
| USING BY REFERENCE fileName
| BY VALUE file-Flags
| BY VALUE file-Mode
| RETURNING ffd
|
| IF ( ffd = ZERO )
| IF ( Testing-Only = "Y" )
| DISPLAY "Failed"
| END-IF
| END-IF
| .
| End Method openRawFile.
|
| *
----------------------------------------------------------------
| IDENTIFICATION DIVISION.
| Method-Id. closePrint.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
| 01 LP-Option PIC X(40).
| 01 I PIC S9(4) COMP-5.
| 01 Buffer PIC X(80).
| PROCEDURE DIVISION.
|
| IF ( ffd = ZERO )
| * MOVE -1 TO Program-Status
| CONTINUE
| ELSE
| CALL "close"
| USING BY VALUE ffd
|
| DISPLAY "CBR_LP_OPTION" UPON Environment-Name
| ACCEPT LP-Option FROM Environment-Value
| ON EXCEPTION MOVE SPACES TO LP-Option
| END-ACCEPT
| PERFORM
| VARYING I FROM LENGTH OF LP-Option BY -1
| UNTIL I < 1
| OR LP-Option(I:1) NOT = SPACE
| MOVE x"00" TO LP-Option(I:1)
| END-PERFORM
|
| MOVE SPACES TO buffer
| STRING "lpr " DELIMITED BY SIZE
| LP-Option DELIMITED BY x"00"
| " " DELIMITED BY SIZE
| fileName DELIMITED BY x"00"
| x"00" DELIMITED BY SIZE
| INTO buffer
| IF ( Testing-Only = "Y" )
| DISPLAY buffer(1:70)
| ELSE
| CALL "system" USING buffer
| END-IF
| END-IF
| .
|
| End Method closePrint.
|
| *
----------------------------------------------------------------
| End Object.
| End Class RawPrint.
Both, in fact, encapsulate the data and isolate the implementation.
So where is there an advantage to using OO in Cobol.
One significant advantage is that multiple objects can be created.
Unlike the callable routine which can only be used as a single print
mechanism, the OO code can be used with multiple instances.
| IDENTIFICATION DIVISION.
| PROGRAM-ID. rawtest2.
| Environment Division.
| Configuration Section.
| Repository.
| Class RawPrint.
| DATA DIVISION.
| WORKING-STORAGE SECTION.
|
| 01 Invoice USAGE OBJECT REFERENCE RawPrint.
| 01 PickSlip USAGE OBJECT REFERENCE RawPrint.
| 01 Link-Function PIC X.
| 01 Link-Name PIC X(80).
| 01 Link-Text PIC X(1024).
|
| PROCEDURE DIVISION.
| Program-RawTest.
|
| MOVE SPACES TO Link-Name
| INVOKE RawPrint "CreateUnNamed"
| RETURNING Invoice
| INVOKE RawPrint "CreateUnNamed"
| RETURNING PickSlip
|
| MOVE "2" TO link-Function
| MOVE "This is line 1 data" TO Link-Text
| PERFORM PrintInv
| MOVE "1" TO link-Function
| MOVE "This is line 3 data" TO Link-Text
| PERFORM PrintInv
| PERFORM PrintSlip
| MOVE "P" TO link-Function
| MOVE "This is line 4 data" TO Link-Text
| PERFORM PrintInv
|
| INVOKE Invoice "closePrint"
| INVOKE PickSlip "closePrint"
|
| STOP RUN
| .
|
| PrintInv.
|
| INVOKE Invoice "writeLine"
| USING Link-Function
| Link-Text
| IF ( Program-Status < ZERO )
| DISPLAY "RawPrint Failed " Link-Function
| END-IF
| .
|
| PrintSlip.
|
| INVOKE PickSlip "writeLine"
| USING Link-Function
| Link-Text
| IF ( Program-Status < ZERO )
| DISPLAY "RawPrint Failed " Link-Function
| END-IF
| .
|
| END PROGRAM rawtest2.
In this particular case there may be little advantage.
BECAUSE you encapsulated the functionality in both, and because you are an
experienced and very capable programmer, there is probably little advantage
for YOU in using OO with COBOL.
It would be a simple matter to remotely inoke the OO class from a web page;
you might have more difficulty using the callable routine...
As you know, I have a number of components written in OO COBOL and I want to
use them in web based applications. I can, but only if I use my own web
server so I can install the fujitsu runtime. I haven't found an ISP yet who
will gladly let me install the runtime... As a result, I'm moving away from
COBOL.
(I'm looking at the possibility of remotely invoking the COBOL components
running on a single web server, from anywhere on the web and any server that
needs them, but, although possible, this is a tad unwieldy as a commercial
solution...)
Bottom line: You are probably right that there is little advantage in using
OO with COBOL.
However, there is great advantage in using OO with languages designed to
support OO...
> One significant advantage is that multiple objects can be created.
> Unlike the callable routine which can only be used as a single print
> mechanism, the OO code can be used with multiple instances.
>
Yes, but that is stretching it a bit...
The called routine could be multitasked if it's calling thread was
multitasked, or run as separate instances under the OS.
Interesting comparison, though, Richard.
Pete.
Another is that with the repository, you get compile time arguement
checking. If you build a Cobol OOP layer, that removes the possibility
of arguement miss-matching between your "user" code and your underlying
"system" code. I agree that the approaches are very same. I prefer the
OOP structure to the traditional, though, for primarilly those two things.
Donald
One of my themes has been that C++ OO solves problems in C that didn't
exist to any noticable extent in Cobol, or in the applications that
Cobol is usually used for.
That is, Cobol had already solved many of the issues that C needed
solutions to.
>> One significant advantage is that multiple objects can be created.
> Yes, but that is stretching it a bit...
No, it is a significant advantage of OO. In fact OO was invented in
Simula for this exact reason. Simula is used to write simulations of,
for example, cars arriving at a petrol station. Objects, such as cars,
are created randomly in some way and eventually leave. Their behaviour
is defined when they are created and modified by events. The essence of
OO is that each is a separate entity.
In this case the program can create as many output streams as required
(and will fit in, say, an array of object references). I actually find
it useful to be able to have two or more configuration objects even
though logically there should only be one configuration, and especially
multiple templating objects so that I can output html and a printed
report at the same time.
> The called routine could be multitasked if it's calling thread was
> multitasked, or run as separate instances under the OS.
Nothing to do with multitasking, just multiple occurances of a class.
See the example code outputting two streams and do that with the called
routine.
Warren Simmons
wsim...@optonline.net
It certainly does for me.
Donald
The second feature which Donald mentions - Repository - I don't have it
in N/E 3.1 but it IS in V 4.0. That's a neat one. At compile time it's
checking forward, (classes which the current compiled program/class
needs to invoke) - to ensure the methods exist or you haven't made a
typo in the method-name. If you haven't crystallized yet in your mind,
the receiving class can be specified with empty methods, e.g. :-
Method-id. "doThis".
End Method "doThis".
The other aspect is get your own support classes RIGHT, DEAD and CENTRE
with decent testing - and you can forget about any glitches which can
occur. Sure you *will* find glitches in the 'requesting' program/class,
(very likely wrong set of sending parameters) but not in the invoked
class - subject to that development testing.
Jimmy
II don't know if MF N/E V4 does or doesn't have this yet)
--
Bill Klein
wmklein <at> ix.netcom.com
"James J. Gavan" <jgavande...@shaw.ca> wrote in message
news:0Y4Td.487098$Xk.335971@pd7tw3no...
It also checks arguement *type*. For example
move "xxx" to numeric-arg of object-reference.
will generate an error that the argument must be numeric. Similarly,
moving a literal that is too long into an alphabetic field will generate
an error.
Donald
I would just like to thank you for posting those examples, I hope it
will help me to get my head around OO.
Robert
" moving a literal that is too long into an alphabetic field "
If the "receiving" field is an Object property? ("generically" truncation on an
alphanumeric move SHOULD not cause an error - as I understand it).
Also, besides CALL prototypes, what you are describing is ALSO available in the
'02 Standard for non-OO code - with "strongly typed" items (see: TYPEDEF).
All of this is simply to say that the compile-time "checking" available to OO
applications is somewhat (mostly? partially?) available - but not default - for
"procedural" code in the '02 Standard (and as an extension to some '85 Standard
compilers, e.g. MF N/E V4)
--
Bill Klein
wmklein <at> ix.netcom.com
"Donald Tees" <donal...@sympatico.ca> wrote in message
news:bu5Td.34051$Am3.9...@news20.bellglobal.com...
Just checked the N/E 4.0 on-line manual for the Index for "P" -
prototype not mentioned. (I think associated with this perhaps,
'refactoring' - a favourite word of our old Ozzie friend Ken Foskey ?)
Jimmy
Glad Richard's example partially turned you on. In no way denigrating
what Richard produced - but it is only the tip of the iceberg; it's the
9/10this below water that make it happen. Nothing quirky about
programming style but getting a handle on Warren's favourite $10 words
like Polymorphism and Encapsulation - how do those fancy words apply.
You are probably already aware both Pete and I give Will (Wilson Price)
five stars for his 'Elements of OO COBOL'. But the one, prior to Will's
book, that clicked for me was Ed Arranga and Frank Coyle. Check
amazon.com, or perhaps something in UK, doing a search on "Edmund
Arranga" - amazon *might* still have some second-hand copies for re-sale.
The example at the back of that book is simplicity itself. If only I
could get Ed to find the diskette containing his sample source ! (Well
it *is* simplicity, but without something like N/E University Edition it
is difficult to follow the sequence, because typically an OO application
jumps backwards and forwards all over the place. Without a compiler, and
access to that damned diskette, one would need to print all the
individual class sources, Index them, so that you could flip
backwards/forwards as they invoke another class).
If anybody can suggest a way - I could cut out the copies from my copy
of the book and then photocopy/scan - can the images be turned into
something readable, (rather than looking like an image produced on a
Xerox with insufficient ink). If we get beyond that phase, who would
'host' the examples to be pulled down by interested parties ?
Jimmy
I believe the current Fujitsu compiler will only generate a warning on
this, though I have always considered a warning to need fixing.
Donald
--
Bill Klein
wmklein <at> ix.netcom.com
"James J. Gavan" <jgavande...@shaw.ca> wrote in message
news:Ms6Td.488515$6l.367903@pd7tw2no...
For obvious reasons I went first looking for prototype in the OO Manual.
As a result of your comment above then tried 'CALL' - not a dicky bird.
Then tried the LRM initially with Prototype - again zilch, but using
your CALL reference it showed up, with the M/F Balloon - indicating an
extension :-
--------------------------------------------------------------------------
Call Prototypes
A call prototype is a program declaration or skeleton program which
serves to define the characteristics of a called subprogram. These
characteristics include the number of parameters required, the type of
these parameters and the calling convention. If a source element
contains a CALL statement referring to a subprogram for which a
prototype exists, the CALL statement is checked against the prototype.
If there is an explicit mismatch, an error is given. If the CALL
statement leaves some characteristics (such as the call convention)
undefined, this is derived from the prototype.
The call prototype is defined as a complete program in which the
EXTERNAL clause is specified in the Program-ID paragraph. The program
structure should consist only of an Identification Division with a
Program-ID paragraph, a Data Division with a Linkage Section, a
PROCEDURE DIVISION header, and optional ENTRY statements. These call
prototypes are placed before the other types of compilation units in a
similar way to multi-program source files.
Note that you must include a copy of the call prototype for every
subprogram to which you want your CALL statements checked before the
IDENTIFICATION DIVISION header of your compilation unit containing the
CALL statements.
--------------------------------------------------------------------------
I read it and can't quite see where it gives me an edge in an OO context
using classes. Donald or Pete, any comments - am I missing something ?
As it stands, M/F provides templates for a skeletal class and skeletal
methods - their format. Having got the id of those templates I can
rename them and substitute my own templates - my style. So I could use
my own dummy and stick in some empty methods. Wont work in N/E V 3.1 but
using N/E 4.1 with REPOSITORY, as Donald pointed out, can do quite a bit
of checking.
Don't want to come across negative - but I don't know how often that is
a valuable approach. Supposing I wanted to invoke Class ImperialMetric
to convert lengths, weights, volumes etc. Sure I can write my requesting
programs/classes :-
invoke ImperialMetric "getCentimetres"
using inches returning centimetres
But 'cautious Harry' here rather tends to figuring out what the invoked
class is going to contain; subsequently doing some final brush-strokes.
When I was into the file handling classes, from info provided -
initially the 'guts' from Will Price, then you, Donald and Pete, I
flip-flopped between the invoking class and the invoked File class -
just to ensure everything was kosher. Now of course, having done it, it
is dead easy and I could quite easily have created invoking classes
with, if you like a prototype for Class ISAMFile. But even there it
actually made sense to determine the ISAMFile class first.
Jimmy
IMHO, it offers NO "advantage" over OO - it simply provides the SAME level of
"compile-time" argument checking as OO does (which is why I brought it up in
this thread).
--
Bill Klein
wmklein <at> ix.netcom.com
"James J. Gavan" <jgavande...@shaw.ca> wrote in message
news:jyaTd.489887$6l.379955@pd7tw2no...
Warren
Jimmy, you have added a new feature to my list.
Hide the logic.
Warren
Well yes..... your use of 'debug'. But I think much more relevant is
your use of the word LEGO - to my mind that hits the nail on the head.
Think of Pete and his COMPONENTS.
Quick example - you might recall my posting MakeAString which will take
say some 100 characters and get rid of intervening superfluous spaces,
returning you one space between each word. Just did it some years back
out of curiosity.
Certainly it was a fit with that query where somebody had :-
01 pic x(100) value "ABCD".
01 pic x(50) value "..................ABCD".
and they just wanted to get back "ABCD" in each case. The questioner was
using Net Express, so my solution was a 'fit'.
OK now on to the Treeview thinggy I'm currently playing with. To make
the labels appearing in the Treeview I had three versions of the
following routine, one for Continent, one for Country and one for the
actual Cheese name, which were like this :-
*>--------------------------------------------------------------
Method-id. "makeTvLabel". *** OLD VERSION
*>--------------------------------------------------------------
01 ls-text pic x(textlength).
Linkage section.
01 lnk-string object reference.
Procedure Division returning lnk-string.
initialize ls-text
String Cheese-ProductCode1
" " delimited by size
Cheese-Name delimited by " "
x"00" delimited by size
into ls-text
End-string
invoke CharacterArray "withLengthValue"
using ws-length, ls-text returning lnk-string
End Method "makeTvLabel".
*>--------------------------------------------------------------
Did above for quickness so the resulting record that gets displayed
could be :-
"123456 Cheddar Cheese...... then x'00'
Note - all the Treeview wants is Cheddar Cheese immediately followed by
the x'00' to cut if off. No big deal here, only some 20 characters. But
what I'm planning for is some 50-60 characters in the displayed names -
for oil/gas plants. Some will be quite short, fair number medium, and
others full 60 characters. So if I went with a fixed 60 chars that's
something like (300 to 600 labels) x 60. (I'm not a tree-hugger, but I
do believe in conserving :-) ).
So gave that MakeAstring some thought - it now has four methods :-
- 'objectWithX00'
- 'ObjectNoX00'
- 'TextNoSpaces
- 'TextWithSpace"
Above doesn't corrupt original method - by their invidiual names they
set flags in MakeAString and then they all invoke self
"ValidateAndCreate" So now I have the revised Treeview method :-
*>--------------------------------------------------------------
Method-id. "makeTvLabel". **** NEW VERSION
*>--------------------------------------------------------------
01 ls-Length pic x(4) comp-5.
01 ls-text pic x(textlength).
01 ls-ReturnedLength pic x(4) comp-5.
01 ls-Results.
05 ls-ReturnLength pic x(4) comp-5.
05 ls-string object reference.
Linkage section.
01 lnk-object object reference.
Procedure Division returning lnk-object.
move textlength to ls-length
initialize ls-text
move Cheese-ProductCode1 to ls-text(1:6)
move Cheese-Name to ls-text(8: )
invoke MakeaString "objectWithX00"
using ls-length, ls-text
returning ls-Results
if ls-ReturnLength <> zeroes
set lnk-Object to ls-string
End-if
End Method "makeTvLabel".
*>--------------------------------------------------------------
In truth, there's not much mileage using the new version - but the
MakeAstring can be called from anywhere and the new method doesn't
include the reference to CharacterArray. (Give the approach some thought
later and perhaps it can be fine tuned).
OK - so I'm messing around with GUIs - but hopefully it illustrates the
principle of using LEGO.
Jimmy
One of the things not mentioned so far, (and this is an opinion,
obviously), is that using an OOP method rather than a mainline program
is simply better structurally. It is true that doing so means a
mainline is required, even if that main program only creates an instance
of the program, invokes the mainline, then destroys the object and exits.
Try doing this. Write a standard program, but instead of performs, try
to use invoke. Here is a skelton in Fujitsu. Please note I just cut and
pasted this together, and have NOT compiled it.
CLASS-ID. BASEOBJ INHERITS FJBASE.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
CLASS FJBASE.
OBJECT.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
******* stuff in here is common to all methods. If
******* made a PROPERTY, then it is accessable externally
77 program-switch-one picture x value "Y" property.
77 end-flag picture x value "N".
PROCEDURE DIVISION.
METHOD-ID. mainline.
DATA DIVISION.
WORKING-STORAGE SECTION.
******* stuff in here is only available to the mainline
PROCEDURE DIVISION.
MAINLINE.
Invoke Self "Start-Up"
perform until end-flag is equal to "Y"
Invoke self main-loop
end-perform.
invoke self "close-out'.
EXIT METHOD.
END METHOD mainline.
******************************************************
METHOD-ID. Start-Up.
DATA DIVISION.
WORKING-STORAGE SECTION.
******* This working storage is local to the method
LINKAGE SECTION.
******* I can pass arguements to the start-up, or any
******* other method.
PROCEDURE DIVISION.
MAIN-LINE.
display "this is the startup".
EXIT METHOD.
END METHOD Start-Up.
******************************************************
METHOD-ID. Close-out.
DATA DIVISION.
PROCEDURE DIVISION.
MAIN-LINE.
display "this is the close out".
EXIT METHOD.
END METHOD Close-out.
******************************************************
METHOD-ID. main-loop.
DATA DIVISION.
PROCEDURE DIVISION.
MAIN-LINE.
display "this is the main-loop".
move "Y" to end-flag.
EXIT METHOD.
END METHOD main-loop.
******************************************************
END OBJECT.
END CLASS BASEOBJ.
Note that instead of one simple working storage area, you get one per
method and a common one. Even when you only break a large program into
several sections like this, that is a major advantage for isolating
problems. It avoids all the problems of fall throughs, exit sections,
etc. etc.
Notice also that switch at the top. I can set that from the mainline
before starting the program, or look at it from the mainline after I
exit. My mainline might parse a command string, for example, set
properties, *then* invoke the mainline.
Each area also has it's own files, in addition to the common files at
the top. A file may be common to the object, or unique to the method, or
both.
I think it a structurally sounder way of building top down programs that
avoids a lot of the traditional Cobol problems. The larger the system,
the more it is usefull.
Donald
In a way, I can relate that to the need on the U1 to do the editing of
fields to remove spaces, and it was done by writing a routine. We would
move a field needing zero replacement with spaces to a common storage
site that was the input field to the zero suppress Object. The output
would be placed in a standard place and picked up by the procedure
needing this feather. Duplicating this zero suppress for each possible
field would be impossible in 1000 words. Extensions were made to the
Object for special needs. I don't remember much more about it now.
At this point, I can't see the objective (or my view of it.) I can see
how MS came up with the library of API's as a result of creating a GUI.
Beyond that, I see a need for a lot of PRE-PLANNING such as the use
of threaded (home, forward and backward), and possibly to new trees as
in Bachman's IDS. Where we tried to apply THAT kind of file system, we
were caught short in our overall understanding of the final objective,
and no project of the necessary size to include everything could get
approved as management generally approved putting out fires, not
building cities. Small lego kits sold better perhaps than the large ones
because the ability to grasp the possibilities were not developed.
Putting out fire mentality didn't hurt that much because the whole
industry, and world economy changed in the meantime. Today, steel
making is much simpler. <G> Which leads me to guess that in the
oil industry, the diversity, and economy did not drive needs in
that way.
However, the people who started CODASYL had as one objective, that
companies would create applications that were commodities and business
would be able to buy the major applications needed. Leaving research
development, and learning in school as the places that would drive
OO development. We are in an area where a lot of simulation is
also used, and that takes care of a lot of the custom programming
needs.
Just my off the top views. Except, I am worried about the documentation
of COBOL programs that look more and more like something from the
electrical engineering field.
However, your example did a good job. Trying to figure out what a lot
of code does makes me feel the object is obfuscation.. A means of
Crypt.
Warren Simmons
Warren
I copied that into a .cbl file, and it compiles cleanly (once I fixed
the margins). However, when I try to "build" an EXE off it, the linker
complains about no entry point. Would I need a second program that
invokes this one, or is there a way to make the "mainline" method a
starting method?
(I'm new with the Fujitsu books as well - I've started looking, but
haven't found the answer yet...)
> Note that instead of one simple working storage area, you get one per
> method and a common one. Even when you only break a large program into
> several sections like this, that is a major advantage for isolating
> problems. It avoids all the problems of fall throughs, exit sections,
> etc. etc.
>
> Notice also that switch at the top. I can set that from the mainline
> before starting the program, or look at it from the mainline after I
> exit. My mainline might parse a command string, for example, set
> properties, *then* invoke the mainline.
>
> Each area also has it's own files, in addition to the common files at
> the top. A file may be common to the object, or unique to the method, or
> both.
>
> I think it a structurally sounder way of building top down programs that
> avoids a lot of the traditional Cobol problems. The larger the system,
> the more it is usefull.
This is just COOL! I've looked at OO before, but it's never made as
much sense as your short example. Thanks! :)
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ / \ / ~ Live from Montgomery, AL! ~
~ / \/ o ~ ~
~ / /\ - | ~ daniel@thebelowdomain ~
~ _____ / \ | ~ http://www.djs-consulting.com ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ GEEKCODE 3.12 GCS/IT d s-:+ a C++ L++ E--- W++ N++ o? K- w$ ~
~ !O M-- V PS+ PE++ Y? !PGP t+ 5? X+ R* tv b+ DI++ D+ G- e ~
~ h---- r+++ z++++ ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
repository. baseobj.
77 my-first object usage object reference baseobj.
Invoke baseobj "new" returning my-first-object. <-create object
invoke my-first-object "mainline". <-use object
set my-first-object to null. <get rid of object.
Donald
Somehow, I managed to post a response to Bill over this. I'll try again.
Yes, that should compile to a DLL. You have to use it from a main
program with a program ID, so it does force the use of a "trigger"
program. It is 5 minutes to starting time, so I'll just rough it out.
The main program to use it contains:
repository. baseobj.
77 my-first object usage object reference baseobj.
Invoke baseobj "new" returning my-first-object. <-create object
invoke my-first-object "mainline". <-use object
set my-first-object to null. <get rid of object.
If you have problems, I can give you a hand lat
er on in the day.
If you look at the original post, I said that you could access that
property from the "mainline", meaning the external program. That was not
very clear, as the example also had a mainline. But to illustrate,
insert the following before you set the object reference to null.
display program-switch-one of my-first-object.
I *think* display can be used with a property, not sure. You can
defnitely MOVE "X" TO program-switch-one of my-first-object.
Donald
message snipped
Hello Warren,
I saw today that you had sent me an email to my hotmail address,
unfortunately, I inadvertently deleted it, perhaps you would send it
again please.
When I looked for your address in the newsgroup, I found it had been
partly obscured, which is why I am replying via the newsgroup.
I mainly use my hotmail address as a spam trap on the grounds that
Microsoft is one of the mostly likely organisations to go after the
spammers. I usually only look at it twice a week.
I usually use robert at jones0086 freeserve co uk with full stops and
at signs interpolated as appropriate.
thanks
Robert
It compiles. In fact, I got both of them to compile. However, now when
I try to "build" the EXE (or the entire project), I get an unresolved
reference to BASEOBJ FACTORY.
Here is the DLL source...
=== DLL ===
@OPTIONS SRF(FREE,FREE)
identification division.
class-id. baseObj inherits FJBASE.
environment division.
configuration section.
repository.
class FJBASE.
object.
data division.
working-storage section.
*> stuff in here is common to all methods. If
*> made a PROPERTY, then it is accessable externally
77 program-switch-one pic X(01) value "Y" property.
77 end-flag pic X(01) value "N".
procedure division.
method-id. mainline.
procedure division.
invoke self "Start-Up"
perform until end-flag = "Y"
invoke self "main-loop"
end-perform
invoke self "close-out"
exit method
. end method mainline.
method-id. Start-Up.
procedure division.
display "this is the startup"
exit method
. end method Start-Up.
method-id. Close-out.
procedure division.
display "this is the close out"
exit method
. end method Close-out.
method-id. main-loop.
procedure division.
display "this is the main-loop"
move "Y" to end-flag.
exit method
. end method main-loop.
end object.
end class BASEOBJ.
=== End DLL ===
And, here is the main program source...
=== EXE ===
@OPTIONS SRF(FREE,FREE)
identification division.
program-id. oo.
environment division.
configuration section.
repository. class baseobj.
data division.
working-storage section.
77 my-first-object usage object reference baseobj.
procedure division.
invoke baseobj "new" returning my-first-object *> create object
invoke my-first-object "mainline" *> use object
display program-switch-one of my-first-object *> display a property
*> that's on the same line in the source...
set my-first-object to null *> get rid of object.
. end program oo.
=== End EXE ===
The basic changes from what you posted is the addition of the word
"class" before "baseobj" in the EXE - it wouldn't compile correctly
without that.
(By the way, the display compiled cleanly, so yes, you can do that with
properties...)
You will find, when you create the DLL, that it also creates a .LIB.
Include that in your link, and it will link fine. The .LIB file should
be called BASEOBJ.LIB.
When you are using the object, you do not need the DLL to link, only the
lib which contains the prototype of the calls. As long as you do not
change the method names/arguments, you can then change the DLL to your
heart's content without re-compiling or re-linking the main program.
Donald
Sweet! :) Works like a charm...
I'm imagining that even in a small-sized OO project, the number of LIB
files would begin to get quite confusing. Is there a way to tell it
"here are all my LIB files" and have it resolve the ones it needs from
there? ("yes" or "no" is fine - I can dig through the book to find the
"how"...)
Thanks again for your help. :)
I use the make facility ... PSTAFF will create a make file as well.
Without a make file (is that "all one place?"), I think the answer is no.
Of course that is no different than if you had used "standard"
subroutines to build it ... at least wih Fujitsu. I am pretty sure you
have to specifically name all the libraries used on Fujitsu builds.
Keep in mind that you *can* put more than one object into a dll, though
I don't normally do it. It would be *very* nice to be able to build one
LIB file that referenced all DLL's, but I do not think that possible ...
as far as I know you get one LIB per DLL.
The property example there was the simplest type of property. You can
also, rather than simply naming the parameter as a property, write a
"set property" or a "get property" *method*. If you wrote a "get
property" method, for example, the
DISPLAY X OF MY-METHOD.
could actually execute code before returning X to the display statement.
Without changing your main code, change the object with the following
code, and see what happens. You should not have to re-compile your main
code for it to work.
******************************************************************
METHOD-ID. GET PROPERTY X.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
77 arguement-displayed PICTURE x.
PROCEDURE DIVISION RETURNING arguement-displayed.
MAINLINE.
Display "The switch inside the object is:"
with no advancing.
MOVE x TO arguement-displayed.
EXIT METHOD.
END METHOD.
*******************************************************************
I think people get too caught up in the OOP theory (OOP theology?) and
miss the fact that the simple construction of the code is superior to
subroutine methodology. It is simply a set of new verbs and such that
allow you to write code in a more structured manner. It results in
cleaner, more modular code, pure and simple. It is also many times more
versatile.
Donald