Tag Archives: CLR - Page 2

Reflection and COBOL

For the last couple of months I have working on Visual Studio 2010 and this include Microsoft CLR v4 and I was recently asked how to write a test that determines at runtime which CLR is being used and what assemblies it uses. I replies would use reflection. So I dropped my friend a mega simple demo… and here it is.

       $set ilusing"System.Reflection"

        01 myAssembly type "Assembly".
        01 usedAssemblyName type "AssemblyName".

        set myAssembly to type "Assembly"::"GetExecutingAssembly"

        display "My exe is " myAssembly::"FullName"
        display "and is using CLR " myAssembly::"ImageRuntimeVersion"
        display "and is loaded from " myAssembly::"Location"
        display "the initial method of this program was "
          myAssembly::"EntryPoint"::"Name"

        display "This assembly references -> "
        perform varying usedAssemblyName
             through myAssembly::"GetReferencedAssemblies"
              display "-> " usedAssemblyName
        end-perform

And the output of the program is:

My exe is clrver, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
and is using CLR v2.0.50727
and is loaded from d:\clrver.exe
the initial method of this program was _MF_ENTRYThis assembly references ->
-> mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-> MicroFocus.COBOL.Runtime, Version=3.6.0.0, Culture=neutral,
PublicKeyToken=0412c5e0b2aaa8f0

Base Class Library, Arrays, Queues and Stacks

Continuing the series of blogs about COBOL and the .Net base class library…

The .Net base class library has a wealth classes and an huge of amount of methods/properties.

The .Net base class library has a key handy namespace that contains are the lovely classes, which is System.Collections.

As you can see from the above link, it does have quite a lot, so for this blob entry I will look at:

  • arrays of numbers
  • queues
  • stacks
  • Lets start the first example by using an array of numbers… just to demonstrate its not just strings you can assign to the arrays using “values”.

           01 numbers  binary-long occurs 10
              values 10 20 30 40 50 10 20 30 40 50.

           01 num       binary-long value 0.
           01 average   binary-double value 0.

           procedure division.
              perform varying num through numbers
                add num to average
              end-perform
              divide average by numbers::"Length" giving average
              display "Average is : " average

    Running the above code gives us:

    Average is : +00000000000000000030

    The next class that is helpful, is the Queue class, this allows us to “Enqueue” and “Dequeue” item using the same methods, the queue is again displayed using the “perform through” syntax.

          $set ilusing"System"
          $set ilusing"System.Collections"

           01 alphabetQueue     type "Queue".
           01 item              object reference.

           set alphabetQueue to new type "Queue"()
           invoke alphabetQueue::"Enqueue"("A item")
           invoke alphabetQueue::"Enqueue"("B item")
           invoke alphabetQueue::"Enqueue"("C item")

           display "The initial queue is: "
           perform varying item through alphabetQueue
             display " " item
           end-perform

           display "".
           display "De-Queue an item: " alphabetQueue::"Dequeue"()

           display "".
           display "Afterwards is: "
           perform varying item through alphabetQueue
             display " " item
           end-perform

    Running the above queue example gives:

    The initial queue is:
     A item
     B item
     C item

    De-Queue an item: A item

    Afterwards is:
     B item
     C item

    Next, lets look at the ‘Stack’ class, this is very similar, expect it uses the “Push”, “Pop” methods and we iterate through the Stack using the ‘perform through’ syntax.

          $set ilusing"System"
          $set ilusing"System.Collections"

           01 alphabetStack     type "Stack".
           01 item              object reference.

           set alphabetStack to new type "Stack"()
           invoke alphabetStack::"Push"("A item")
           invoke alphabetStack::"Push"("B item")
           invoke alphabetStack::"Push"("C item")

           display "The initial stack is: "
           perform varying item through alphabetStack
             display " " item
           end-perform

           display "".
           display "Pop item: " alphabetStack::"Pop"()

           display "".
           display "Afterwards is: "
           perform varying item through alphabetStack
             display " " item
           end-perform

    Running the above stack example gives:

    The initial stack is:
     C item
     B item
     A item

    De-Stack an item: C item

    Afterwards is:
     B item
     A item

    As you can see using the base class library collection classes with COBOL is just as easy as using C#… so if you are already using COBOL… continue and try out the .Net base class library.. it really is very easy to use and it will make you more productive.. so please explore and enjoy .Net and its Base Class library.

    Detecting the use Mono CLR dynamically

    While developing something that could be used on Mono on Windows, Mono on Unix and on Windows with Microsoft’s CLR, I needed to be sensitive to the environment but didn’t want to conditionally compile my code different. So I put together a quick class to help.. Below is the C# code with pics of it running on Windows/Mac…

    using System;
    using System.Reflection;

    namespace Gennard.Net
    {
        public class CLRUtils
        {
            private static readonly bool isMono= Type.GetType("Mono.Runtime") == null ? false : true;

            private static readonly int eOSp = (int)Environment.OSVersion.Platform;
            private static readonly bool isUnix =  (eOSp == 4) || (eOSp == 128);

            /* Class Properties */
            public static bool IsMono { get { return isMono; } }
            public static bool IsUnix { get { return isUnix; } }

            public static void Main()
            {
                Console.WriteLine("Are we using Mono? : "+IsMono);
                Console.WriteLine("Are we using Unix? : "+IsUnix);
            }
        }
    }

    The taste of the pudding mix.. is in the eating.. so lets see it working…

    On Windows....

    On the Mac, we get....

    Too Iterate or not…

    Over the next couple of weeks, I will explore some of the reasons why I think managed environments are good for COBOL.

    So.. lets the show on the road…

    Setting up arrays/occurs items in COBOL and manipulating them can be painful. Lets look at some traditional code for playing around with a “months” table.

           01 month-val.
               05  FILLER                    PIC X(10)  value "January".
               05  FILLER                    PIC X(10)  value "February".
               05  FILLER                    PIC X(10)  value "March".
               05  FILLER                    PIC X(10)  value "April".
               05  FILLER                    PIC X(10)  value "May".
               05  FILLER                    PIC X(10)  value "June".
               05  FILLER                    PIC X(10)  value "July".
               05  FILLER                    PIC X(10)  value "August".
               05  FILLER                    PIC X(10)  value "September".
               05  FILLER                    PIC X(10)  value "October".
               05  FILLER                    PIC X(10)  value "November".
               05  FILLER                    PIC X(10)  value "December".

           01 month-tab redefines month-val.
               05  months occurs 12 times.
                   10  month-NAME            PIC X(10).

           01 month                          PIC 99.

           01 secondQuarterMonths            pic x(70).
     
           display "The months are:"
           perform varying month from 1 by 1 until month equals 12
             display " " months(month)    
           end-perform

           display " "
           display "The second quarter months are: "

           string months(4) delimited by space
                  "/" delimited by size
                  months(5) delimited by space
                  "/" delimited by size
                  months(6) delimited by space
              into secondQuarterMonths
              on overflow
                 display "FATAL Error - secondQuarterMonths is too small"
                 stop run
           end-string

           display " " secondQuarterMonths

    Now, imagine we can use one or two of the .Net’s base class libraries combined with some nifty natural extensions to COBOL to do some of the heavy lifting.

    Defining the month item as a native .Net type ie: a string combined with using the base class libraries Split methods allows us to setup a array quickly.

            01 commaDelimited       string value
             "January,February,March,April,May,June,July,August," &
             "September,October,November,December".

            01 months              string occurs any.
            01 month               string.

            01 secondQuarterMonths  string.

            set months to commaDelimited::"Split"(',')

            display "The months are: "
            perform varying month through months
              display " " month
            end-perform

            display " "
            display "The second quarter months are: "

            set secondQuarterMonths to type "System.String"::"Join"('/', months, 3, 3)

            display " " secondQuarterMonths

    The .Net version, besides being smaller feels much easier to read, especially if you have any exposure to the .Net base class library from other languages such as C# or VB.Net.

    Of course in a real world example, we don’t need to use the split method to setup an array, we could just use the “values” clause… for example:

          01 months  string occurs 12 values
             "January" "February" "March" "April" "May" "June"
             "July" "August" "September" "October" "November" "December".

           01 month string.

               perform varying month through months
                   display month
               end-perform

    If however you don’t want to hardcode the months, you can always use: CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName() in the System.Globalization namespace. :-)

    So… lets just do it…

           01 Months string occurs any.
           01 Month string.

           set Months to type "System.Globalization.DateTimeFormatInfo"::
              "CurrentInfo"::"MonthNames"
               
           perform varying Month through Months
              display Month
           end-perform

    Now, I hope you feel like I do that COBOL and .Net are indeed perfect partners to each other.


    The above COBOL .Net code will execute on Micro Focus Net Express and I suspect it will also work on Fujitsu’s netCobol too.