Iterative systems .Collections.List in Fujitsu COBOL

How do I go through the collection?

I am in the trial version of the Fujitsu / Alchemy compiler and get slow and poor support from the provider.

I basically want to pass List from C # to COBOL, and then let COBOL use it and possibly update it.

In C #, the usual way to iterate through a collection is to use the "foreach" construct.

However, the C # "foreach" construct is a shortcut to the following:

private static void test1() { List<IDMSMapField> list1 = new List<IDMSMapField>(); int listSize = list1.Count; // was just checking exact variablename and case here to copy into COBOL code. int itemNumber = 0; System.Collections.Generic.List<IDMSMapField>.Enumerator enumerator1 = list1.GetEnumerator(); while (enumerator1.MoveNext()) { Console.Write("Okay" + enumerator1.Current); } } 

I can write this in COBOL if you can help me figure it out to declare this class:

 System.Collections.Generic.List<IDMSMapField>.Enumerator 

The Enumerator structure is documented on the Microsoft MSDN site .

It says that "Enumerator" is a Struct, not a class!

From what I can say in the guide "CreateCOBOLfromDotnetFrameworkDox.pdf", structures are defined as classes in COBOL REGISTRATION.

Example from the manual:

 Define specifiers for structure in REPOSITORY, and any struct members: CLASS STRUCT-name AS "struct-namespace" PROPERTY PROP-struct-member AS "external-property-name" Handle structures like classes. Eg object to store a struct instance: 01 struct-object OBJECT REFERENCE STRUCT-name. 

Below I repeat some of the options that I tried, which all failed to compile, due to an "impossible to solve" error. If you can show me how to make this clear, I think we can move forward.

1.

  REPOSITORY. CLASS CLASS-LIST AS "System.Collections.Generic.List<>" CLASS STRUCT-Enumerator AS "System.Collections.Generic.List<>.Enumerator" . 

The error in the second line:

error JMN1795I-S: Named reference 'System.Collections.Generic.List <>. Enumerator 'cannot be resolved.

  • The exact error for this is:

      REPOSITORY. CLASS CLASS-LIST AS "System.Collections.Generic.List<>" CLASS STRUCT-Enumerator AS "System.Collections.Generic.List<T>.Enumerator" . 

JMN1795I-S error: The named link "System.Collections.Generic.List.Enumerator" cannot be resolved.

  • Same error:

    WAREHOUSE. CLASS CLASS-LIST AS "System.Collections.Generic.List <>" CLASS STRUCT-Enumerator as "System.Collections.Generic.List.Enumerator".

JMN1795I-S error: The named link "System.Collections.Generic.List.Enumerator" cannot be resolved.

Another option is to consider it as an array, but I am also fixated on this.

 REPOSITORY. CLASS LIST-IDMSMapField AS "System.Collections.Generic.List<>[]" CLASS CLASS-IDMSMapField AS "Lightyear.ERCB.IDMSDC.IDMSMapField" CLASS CLASS-LIST-IDMSMapField EXPANDS LIST-IDMSMapField USING CLASS-IDMSMapField. METHOD-ID. TW1DR4000-PF06 AS "TW1DR4000_PF06". DATA DIVISION. WORKING-STORAGE SECTION. 01 MapFieldItem USAGE OBJECT REFERENCE CLASS-IDMSMapField. LINKAGE SECTION. 01 MapFieldList USAGE OBJECT REFERENCE CLASS-LIST-IDMSMapField. PROCEDURE DIVISION... ... SET MapFieldItem TO MapFieldList(1). 

error JMN2671I-S: ':' must be specified in the link modifier. ':' is assumed.

I think the compiler sees (1) as a substring operation.

+4
source share
2 answers

It took some time, but here is a complete working sample. There were a few more tricks that fell into properties, and moving property values, such as Count, into the COBOL variable with the corresponding USGE clause. The keyword "EXPANDS" (in the repository) is another key part of the solution.

In my real program, I will get a list in the LINKAGE section, and I will have a list of more complex objects ... but the sample code is a simpler script that stands alone and works "as is".

  IDENTIFICATION DIVISION. PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main". ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. REPOSITORY. CLASS List AS "System.Collections.Generic.List<>" CLASS SysString AS "System.String" CLASS SysBoolean AS "System.Boolean" CLASS ListString EXPANDS List USING SysString CLASS Enumerator AS "System.Collections.Generic.List<>+Enumerator" CLASS StringEnumerator EXPANDS Enumerator USING SysString PROPERTY PROP-Count AS "Count" PROPERTY PROP-Current AS "Current" . DATA DIVISION. WORKING-STORAGE SECTION. 01 myList OBJECT REFERENCE ListString. 01 myEnum OBJECT REFERENCE StringEnumerator. 01 myBooleanEnumResult OBJECT REFERENCE SysBoolean. 01 myDotNetString OBJECT REFERENCE SysString. 01 myLoopCounter PIC 9(4) value zero. 01 myCobolCount PIC S9(9) COMP-5 VALUE ZERO. 01 myCobolString PIC X(30) value spaces. 01 YN-END-LOOP PIC X value "N". 01 WS-ACCEPT-INPUT PIC X(80) value spaces. PROCEDURE DIVISION. 1000-START. INVOKE ListString "NEW" returning myList. INVOKE myList "Add" using "Apples" INVOKE myList "Add" using "Bananas" INVOKE myList "Add" using "Orange" SET myCobolCount to PROP-Count of myList DISPLAY "Size of MyList = " myCobolCount INVOKE myList "GetEnumerator" returning myEnum. PERFORM UNTIL YN-END-LOOP = "Y" INVOKE myEnum "MoveNext" returning myBooleanEnumResult * How to test for Boolean, True = B'1' and False = B'0' IF myBooleanEnumResult = B'0' MOVE "Y" TO YN-END-LOOP ELSE SET myDotNetString TO PROP-Current of myEnum ADD 1 TO myLoopCounter SET myCobolString to myDotNetString DISPLAY myLoopCounter " " myCobolString END-IF END-PERFORM DISPLAY "END OF PROGRAM - PRESS ENTER TO END" ACCEPT WS-ACCEPT-INPUT . END PROGRAM MAIN. 
+2
source

Using the implementation of Micro Focus.NET, the code can use the "do different" extension to move through the list.

So, the modified version:

  IDENTIFICATION DIVISION. PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main". ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. REPOSITORY. CLASS List AS "System.Collections.Generic.List" CLASS SysString AS "System.String" CLASS SysBoolean AS "System.Boolean" CLASS ListString EXPANDS List USING SysString PROPERTY PROP-Count AS "Count" PROPERTY PROP-Current AS "Current" . DATA DIVISION. WORKING-STORAGE SECTION. 01 myList OBJECT REFERENCE ListString. 01 myLoopCounter PIC 9(4) value zero. 01 myCobolCount PIC S9(9) COMP-5 VALUE ZERO. 01 myCobolString PIC X(30) value spaces. 01 WS-ACCEPT-INPUT PIC X(80) value spaces. PROCEDURE DIVISION. 1000-START. INVOKE ListString "NEW" returning myList. INVOKE myList "Add" using "Apples" INVOKE myList "Add" using "Bananas" INVOKE myList "Add" using "Orange" SET myCobolCount to PROP-Count of myList DISPLAY "Size of MyList = " myCobolCount move 0 to myLoopCounter PERFORM varying myCobolString through myList DISPLAY myLoopCounter " " myCobolString ADD 1 to myLoopCounter END-PERFORM DISPLAY "END OF PROGRAM - PRESS ENTER TO END" ACCEPT WS-ACCEPT-INPUT . END PROGRAM MAIN. 

Further, instead of using the syntax of the repository and its extension, you can use the built-in declaration, for example:

  IDENTIFICATION DIVISION. PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main". WORKING-STORAGE SECTION. 01 myList type "System.Collections.Generic.List"[string]. 01 myLoopCounter PIC 9(4) value zero. 01 myCobolCount PIC S9(9) COMP-5 VALUE ZERO. 01 myCobolString PIC X(30) value spaces. 01 WS-ACCEPT-INPUT PIC X(80) value spaces. PROCEDURE DIVISION. 1000-START. INVOKE type "System.Collections.Generic.List"[string]::"NEW" returning myList INVOKE myList "Add" using "Apples" INVOKE myList "Add" using "Bananas" INVOKE myList "Add" using "Orange" SET myCobolCount TO myList::"Count" DISPLAY "Size of MyList = " myCobolCount MOVE 0 TO myLoopCounter PERFORM varying myCobolString through myList DISPLAY myLoopCounter " " myCobolString ADD 1 TO myLoopCounter END-PERFORM DISPLAY "END OF PROGRAM - PRESS ENTER TO END" ACCEPT WS-ACCEPT-INPUT . END PROGRAM MAIN. 

In any case, I just like that we can do this in COBOL, no matter what product is used. Enjoy ...

0
source

All Articles