BitBabel Terminal V0.5...

About BitBabel Examples Contact

About BitBabel


BitBabel is an application written in .net 6 (C#) that makes code conversion from COBOL to C# possible. It is available as an online web portal in which you can work with your encrypted files in a subscription manner or as a command line tool available as a time limited licence to run in your local environment.
The latter licence also enables a layer of code visitors that may help in more automated refactoring logic!

Currently there is only COBOL parser and C# generator being developed.
The transformed code tries to be as close to state-of-art as possible thus the output may contain constructs like:
- arithmetic operations using normal binary operators notation
- data structures and interfaces
- try-catch blocks
- dependency injection artifacts
- many more

There is a draw back of such an approach - it may happen that i.e. some arithmetic operations may provide slightly different results. The good point is the resulting code will look like C# rather than C#OBOL.
See supported COBOL constructs for more details on where the current implementation is.

What BitBabel is NOT:
- it is not a one-click tool that will convert whole mainframe project to .net
- it will not refactor or cleanup your business logic
- it is not a COBOL execution environment
- it will not write unit test for transformed code
- it is not a free tool

What BitBabel MAY do for you:
- it may help you moving away from mainframe
- it may help you moving to either on-premise or cloud environments
- it may help you save years of rewriting your mainframe solution to other platform
- it may help you refactor your business logic with built-in model visitors layer (only as command line tool)
- it may help you in unit-testing your business logic thanks to dependency injection artifacts

Menu

Currently supported COBOL constructs

:
ARRAY(?)
TEXT(?:?)
MOVE [FUNCTION ]? TO ?
SET ?[ OF ?] TO ?
GO TO ?
STOP RUN
EXIT (PROGRAM|PARAGRAPH)
GOBACK
[IDENTIFICATION|DATA|ENVIRONMENT] DIVISION
PROCEDURE DIVISION[ USING ? RETURNING ?]*****
[WORKING-STORAGE|LOCAL-STORAGE|LINKAGE|CONFIGURATION|?] SECTION
01 ?
88 ? VALUE (?|ZERO|ZEROS|ZEROES|SPACE|SPACES)
88 ? VALUES ?[ THRU|THROUGH ?]
01 ?[ REDEFINES ?][ OCCURS[ ? TO] ? TIMES] PIC ?[ OCCURS[ ? TO] ? TIMES[ [ASCENDING KEY IS ?][DESCENDING KEY IS][INDEXED BY]]][ USAGE IS ?]
01 [? ]PIC[TURE[ IS]] ?[ JUSTIFIED RIGHT][ VALUE (?|ZERO|ZEROS|ZEROES|HIGH-VALUES|HIGH-VALUE|LOW-VALUES|LOW-VALUE)]
PROGRAM-ID ?
AUTHOR[-NAME] ?***
DATE-WRITTEN ?***
DATE-COMPILED ?***
SOURCE-COMPUTER ?***
OBJECT-COMPUTER ?***
SPECIAL-NAMES DECIMAL-POINT IS COMMA
PERFORM PARAGRAPH ?
ADD ?[[ CORR[ESPONDING]] TO ?| GIVING ?][ ROUNDED][[ ON SIZE ERROR ?][ NOT ON SIZE ERROR ?] END-ADD]
SUBTRACT ?[[ CORR[ESPONDING]] FROM ?| GIVING ?][ ROUNDED][[ ON SIZE ERROR ?][ NOT ON SIZE ERROR ?] END-SUBSTRACT]
MULTIPLY ? BY ?[ GIVING ?][ ROUNDED][[ ON SIZE ERROR ?][ NOT ON SIZE ERROR ?] END-MULTIPLY]
DIVIDE ? [BY|INTO] ?[ GIVING ?][ ROUNDED][ REMAINDER ?][[ ON SIZE ERROR ?][ NOT ON SIZE ERROR ?] END-DIVIDE]
COMPUTE ?[ ROUNDED] = [FUNCTION ]?
DISPLAY ?[[ WITH] NO ADVANCING]
ACCEPT ?[ FROM (DATE[ YYYYMMDD]|DAY[ YYYYDDD]|TIME|DAY-OF-WEEK)]
IF ? THEN ?[ ELSE ?] END-IF
PERFORM [?][ THRU|THROUGH ?][ [WITH] TEST [AFTER|BEFORE]][ VARYING ? FROM ? BY ?][ UNTIL ?][ END-PERFORM]
PERFORM [?][ THRU|THROUGH ?] ? TIMES[ END-PERFORM]
CALL ?[ USING[ BY VALUE|BY REFERENCE] ? RETURNING ?][ ON EXCEPTION ? END-CALL]
CANCEL ?
EVALUATE ? WHEN ? WHEN OTHER ? END-EVALUATE
EVALUATE TRUE WHEN ? THEN OTHER ? END-EVALUATE
INITIALIZE ?[ REPLACING ? BY ?]
IMPORT ?
COPY ?
GO TO ?
STRING ? INTO ?[ [WITH ]POINTER ?][ ON OVERFLOW ?][ NOT ON OVERFLOW ?] END-STRING
UNSTRING ? DELIMITED[ BY][ ALL] ?[ OR[ BY][ ALL] ?] INTO ?[ DELIMITER[ IN] ?][ COUNT[ IN] ?][ [WITH ]POINTER ?][ TALLYING ?][ ON OVERFLOW ?][ NOT ON OVERFLOW ?] END-UNSTRING
INSPECT ? TALLYING[ ?|CHARACTERS] FOR[ ALL|LEADING][ (BEFORE|AFTER)[ INITIAL] ?]****
INSPECT ? REPLACING[ ALL|LEADING|FIRST][ ?|CHARACTERS] BY ?[ (BEFORE|AFTER)[ INITIAL] ?]****
INSPECT ? CONVERTING ? TO ?[ (BEFORE|AFTER)[ INITIAL] ?]
SEARCH[ ALL] ?[ VARYING ?][ AT END ?][ WHEN ?] END-SEARCH
JSON PARSE ? INTO ?[[ WITH] DETAIL][ NAME[ OF] ?[ IS] (?|OMITTED)][ SUPPRESS ?][ CONVERTING ?[ FROM][ JSON] [BOOL[EAN]][ USING] ?[ AND ?][ ALSO ?]][ ON EXCEPTION ?][ NOT ON EXCEPTION ?] END-JSON JSON GENERATE ? FROM ?[ COUNT[ IN] ?][ NAME[ OF] ?[ IS] (?|OMITTED)][ SUPPRESS ?[ EVERY[ [NON]NUMERIC]][ WHEN ?]][ CONVERTING ?[ FROM][ JSON] [BOOL[EAN]][ USING] ?[ AND ?][ ALSO ?]][ ON EXCEPTION ?][ NOT ON EXCEPTION ?] END-JSON XML GENERATE ? FROM ?[ COUNT[ IN] ?][ WITH [ENCODING ?|XML-DECLARATION|ATTRIBUTES]][ NAME[ OF] ?[ IS] ?][ TYPE [ OF] ?[ IS] (ATTRIBUTE|CONTENT|ELEMENT)][ SUPPRESS ?[ EVERY[ [NON]NUMERIC[ ATTRIBUTE|CONTENT|ELEMENT]]][ WHEN ?]][ ON EXCEPTION ?][ NOT ON EXCEPTION ?] END-XML EXEC SQL INCLUDE ? END-EXEC
EXEC SQL ? END-EXEC *
EXEC CICS ? END-EXEC **
INTRINSIC FUNCTIONS

* SQL dialect transformation is not yet fully included
** CICS calls are translated into external dependency calls to be implemented by user
*** These constructs are ignored and does not produce any output
**** INSPECT TALLYING and REPLACING combination is also supported
***** DECLARATIVES are not supported

This list should be taken literally - if you cannot find a construct that matches it's probably not yet implemented.
These won't be implemented anytime soon:
- XML parsing
- file handling
- pointers (i.e. ALLOCATE/FREE)
- ENTRY
About

Currently supported COBOL intrinsic functions

:
LENGTH
ULENGTH
UPPER-CASE
LOWER-CASE
USUBSTR
TRIM
TRIML
TRIMR
REVERSE
UWIDTH
NUMVAL
NUMVAL-C
ORD
CHAR
DISPLAY-OF
NATIONAL-OF
UPOS
USUPLEMENTARY
UVALID
PRESENT-VALUE
ANNUITY
UUID4
RANDOM
RANGE
MAX
ORD-MAX
MIN
ORD-MIN
SUM
MEAN
MEDIAN
MIDRANGE
VARIANCE
STANDARD-DEVIATION
MOD
REM
SQRT
LOG
LOG10
FACTORIAL
SIGN
SIN
ASIN
COS
ACOS
TAN
ATAN
INTEGER
INTEGER-PART
INTEGER-OF-DATE
INTEGER-OF-DAY
DATE-OF-INTEGER
DAY-OF-INTEGER
EXTRACT-DATE-TIME
CURRENT-DATE
DATEVAL
DATE-TO-YYYYMMDD
DAY-TO-YYYYDDD
YEAR-TO-YYYY
E
PI
BIT-OF
BIT-TO-CHAR
HEX-OF
HEX-TO-CHAR
BYTE-LENGTH
Supported COBOL constructs
IDENTIFICATION DIVISION.
PROGRAM-ID. DAYS.

DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 WEEK.
        02 DAY-1 PIC X(11).
        02 DAY-2 PIC X(11).
        02 DAY-3 PIC X(11).
        02 DAY-4 PIC X(11).
        02 DAY-5 PIC X(11).
        02 DAY-6 PIC X(11).
        02 DAY-7 PIC X(11).
    01 WS-DAY REDEFINES WEEK PIC X(11) OCCURS 7 TIMES.
    LOCAL-STORAGE SECTION.
    01 LS-INDEX PIC 9(1).
    01 TIME PIC S9(15) COMP-3.

PROCEDURE DIVISION.
    PERFORM INITIALIZE-DAYS
    PERFORM VARYING LS-INDEX FROM 1 BY 1 UNTIL LS-INDEX > 7
        DISPLAY WS-DAY(LS-INDEX)
    END-PERFORM
    EXEC CICS ASKTIME ABSTIME(TIME) END-EXEC
    STOP RUN.

INITIALIZE-DAYS.
    MOVE 'Monday' TO WS-DAY(1)
    MOVE 'Tuesday' TO WS-DAY(2)
    MOVE 'Wednesday' TO WS-DAY(3)
    MOVE 'Thursday' TO WS-DAY(4)
    MOVE 'Friday' TO WS-DAY(5)
    MOVE 'Saturday' TO WS-DAY(6)
    MOVE 'Sunday' TO WS-DAY(7).
                Back
                
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN.

DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 MATH-STRONG PIC X(11) VALUE 'MATH-STRONG'.
    LOCAL-STORAGE SECTION.
    01 STRONG PIC 9(3).
    01 RESULT PIC 9(10).

PROCEDURE DIVISION.
    MOVE 5 TO STRONG
    CALL MATH-STRONG USING BY VALUE STRONG RETURNING RESULT
    DISPLAY STRONG "! = " RESULT
    STOP RUN.
                Back
                
IDENTIFICATION DIVISION.
PROGRAM-ID. MATH-STRONG.

DATA DIVISION.
    LOCAL-STORAGE SECTION.
    01 COUNTER PIC 9(3).
    LINKAGE SECTION.
    01 INPUT PIC 9(3).
    01 RESULT PIC 9(10).

PROCEDURE DIVISION USING BY VALUE INPUT RETURNING RESULT.
STRONG.
    EVALUATE TRUE
        WHEN INPUT IS NEGATIVE
            DISPLAY "Value cannot be negative."
        WHEN OTHER
            PERFORM DO-INIT
            PERFORM UNTIL COUNTER LESS THAN OR EQUAL TO INPUT
                MULTIPLY RESULT BY COUNTER GIVING RESULT
                ADD 1 TO COUNTER
            END-PERFORM
    END-EVALUATE
    STOP RUN.

DO-INIT.
    MOVE 1 TO RESULT
    MOVE 1 TO COUNTER.                
                Back
                
IDENTIFICATION DIVISION.
PROGRAM-ID. STUDENTS.

DATA DIVISION.
    LINKAGE SECTION.
    01 ID PIC 9(9).
    01 STUDENT.
        02 ID PIC 9(9).
        02 FIRST-NAME PIC X(16).
        02 LAST-NAME PIC X(32).
        02 AGE PIC 9(3) VALUE 0.
        02 GENDER PIC X(1).
            88 MALE VALUE 'M'.
            88 FEMALE VALUE 'F'.
            88 VALID VALUES 'M' 'F'.
    EXEC SQL
        IMPORT SQLCA
    END-EXEC.

PROCEDURE DIVISION USING BY REFERENCE RETURNING STUDENT.
    EXEC SQL
        SELECT FNAME, LNAME, AGE
        FROM STUDENTS
        INTO :FIRST-NAME, :LAST-NAME, :AGE
        WHERE ID = :ID
    END-EXEC
    IF SQLCODE >= 100 THEN
        INITIALIZE STUDENT
    END-IF.
                Back
                
using AlienSoftworks.BitBabel.Cobol;
using AlienSoftworks.BitBabel.Data;
using AlienSoftworks.BitBabel.IO;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public class Days : DataStructureBase, IDays
    {
        private IConsole _console;
        private IExternalCallComponent _externalCallComponent;

        public Days(IConsole console, IExternalCallComponent externalCallComponent, DataBuffer buffer = null, int startAt = 0)
            : base(buffer, startAt)
        {
            _console = console;
            _externalCallComponent = iExternalCallComponent;
        }

        private static IWeek TheWeek
        {
            get { return (IWeek)DataStructureBase.GetProperty(typeof(Days), nameof(Days.TheWeek)); }
            set { DataStructureBase.SetProperty(typeof(Days), nameof(Days.TheWeek), value); }
        }

        [CobolRedefinition("X(11)", nameof(Days.TheWeek), 7)]
        private static IList WsDay
        {
            get { return (IList)DataStructureBase.GetProperty(typeof(Days), nameof(Days.WsDay)); }
            set { DataStructureBase.SetProperty(typeof(Days), nameof(Days.WsDay), value); }
        }

        [CobolPicture("9(1)")]
        private byte LsIndex
        {
            get { return (byte)GetProperty(nameof(LsIndex)); }
            set { SetProperty(nameof(LsIndex), value); }
        }

        [CobolPicture("S9(15)")]
        private long Time
        {
            get { return (long)GetProperty(nameof(Time)); }
            set { SetProperty(nameof(Time), value); }
        }

        public async Task Process(CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
            Main();
        }

        private void Main()
        {
            InitializeDays();
            for (LsIndex = (byte)((byte)1 - (byte)1); LsIndex <= ((byte)7 - (byte)1); LsIndex = (byte)(LsIndex + (byte)1))
            {
                _console.Write("{0}", WsDay[(LsIndex - 1)]);
            }

            {
                var inputParameters = new System.Collections.Generic.Dictionary();
                var outputParameters = new System.Collections.Generic.Dictionary)>();
                inputParameters["ABSTIME"] = Time;
                outputParameters["ABSTIME"] = (typeof(long), _ => Time = (long)_);
                _externalCallComponent.Execute(
                    "ASKTIME",
                    inputParameters,
                    outputParameters);
            }
        }

        private void InitializeDays()
        {
            WsDay[(1 - 1)] = "Monday";
            WsDay[(2 - 1)] = "Tuesday";
            WsDay[(3 - 1)] = "Wednesday";
            WsDay[(4 - 1)] = "Thursday";
            WsDay[(5 - 1)] = "Friday";
            WsDay[(6 - 1)] = "Saturday";
            WsDay[(7 - 1)] = "Sunday";
        }

        public class Week : DataStructureBase, IWeek
        {
            public Week(DataBuffer buffer = null, int startAt = 0)
                : base(buffer, startAt)
            {
            }

            public virtual string Day1
            {
                get { return (string)GetProperty(nameof(Day1)); }
                set { SetProperty(nameof(Day1), value); }
            }

            public virtual string Day2
            {
                get { return (string)GetProperty(nameof(Day2)); }
                set { SetProperty(nameof(Day2), value); }
            }

            public virtual string Day3
            {
                get { return (string)GetProperty(nameof(Day3)); }
                set { SetProperty(nameof(Day3), value); }
            }

            public virtual string Day4
            {
                get { return (string)GetProperty(nameof(Day4)); }
                set { SetProperty(nameof(Day4), value); }
            }

            public virtual string Day5
            {
                get { return (string)GetProperty(nameof(Day5)); }
                set { SetProperty(nameof(Day5), value); }
            }

            public virtual string Day6
            {
                get { return (string)GetProperty(nameof(Day6)); }
                set { SetProperty(nameof(Day6), value); }
            }

            public virtual string Day7
            {
                get { return (string)GetProperty(nameof(Day7)); }
                set { SetProperty(nameof(Day7), value); }
            }
        }
    }
}
                Back
                
using AlienSoftworks.BitBabel.Data;
using AlienSoftworks.BitBabel.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public class Main : IMain
    {
        private IMathStrong _mathStrong;
        private IConsole _console;

        public Main(IMathStrong mathStrong, IConsole console)
        {
            _mathStrong = mathStrong;
            _console = console;
        }

        [CobolPicture("X(11)")]
        private static string MathStrong { get; set; } = "MATH-STRONG";

        [CobolPicture("9(3)")]
        private ushort Strong { get; set; }

        [CobolPicture("9(10)")]
        private ulong Result { get; set; }

        public async Task Process(CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
            Main();
        }

        private void Main()
        {
            Strong = (ushort)5;
            Result = _mathStrong.Process(Strong);
            _console.Write("{0}{1}{2}", Strong, "! = ", Result);
        }
    }
}
                Back
                
using AlienSoftworks.BitBabel.Data;
using AlienSoftworks.BitBabel.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public class MathStrong : IMathStrong
    {
        private IConsole _console;

        public MathStrong(IConsole console)
        {
            _console = console;
        }

        [CobolPicture("9(3)")]
        private ushort Counter { get; set; }

        [CobolPicture("9(3)")]
        private ushort Input { get; set; }

        [CobolPicture("9(10)")]
        private ulong Result { get; set; }

        public async Task<ulong> Process(ushort input, CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
            Input = input;
            Main();
            return Result;
        }

        private void Main()
        {
            if (Input < 0.0M)
            {
                _console.Write("{0}", "Value cannot be negative.");
            }
            else
            {
                DoInit();
                while (Counter > Input)
                {
                    Result = Result * Counter;
                    Counter = (ushort)((ushort)1 + Counter);
                }
            }

        }

        private void DoInit()
        {
            Result = 1ul;
            Counter = (ushort)1;
        }
    }
}
                Back
                
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public interface IDays
    {
        Task Process(CancellationToken cancellationToken);
    }
}
                Back
                
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public interface IMain
    {
        Task Process(CancellationToken cancellationToken);
    }
}
                Back
                
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public interface IMathStrong
    {
        Task<ulong> Process(ushort input, CancellationToken cancellationToken);
    }
}
                Back
                
using AlienSoftworks.BitBabel.Data;
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public class Students : IStudents
    {
        private static string _sqlQuery = 
        @"SELECT FNAME, LNAME, AGE
               FROM STUDENTS
               INTO @firstName, @lastName, @age
               WHERE ID = @id";

        private IDataAccessComponent _dataAccessComponent;

        public Students(IDataAccessComponent iDataAccessComponent)
        {
            _dataAccessComponent = iDataAccessComponent;
        }

        [CobolPicture("9(9)")]
        private uint Id { get; set; }

        private IStudent TheStudent { get; set; }

        public async Task<IStudent> Process(CancellationToken cancellationToken)
        {
            {
                var outputParameters = new Dictionary<string, (Type, Action<object>)>();
                outputParameters["firstName"] = (typeof(string), _ => TheStudent.FirstName = (string)_);
                outputParameters["lastName"] = (typeof(string), _ => TheStudent.LastName = (string)_);
                outputParameters["age"] = (typeof(ushort), _ => TheStudent.Age = (ushort)_);
                outputParameters["id"] = (typeof(uint), _ => Id = (uint)_);
                var rows = await _dataAccessComponent.Execute(
                    _sqlQuery,
                    null,
                    null,
                    outputParameters,
                    cancellationToken);
                if (rows == 0)
                {
                    DataStructure.Initialize(
                        this,
                        nameof(TheStudent),
                        new bool?[0],
                        new object[0],
                        false);
                }
            }

            return TheStudent;
        }

        public class Student : IStudent
        {
            private static string[] _validValues = new string[] { "M", "F" };

            public Student()
            {
                FirstName = "";
                LastName = "";
                Gender = "";
            }

            public string this[int index, int length]
            {
                get { return this.GetFragment(index, length); }
                set { this.SetFragment(index, length, value); }
            }

            public virtual uint Id { get; set; }

            public virtual string FirstName { get; set; }

            public virtual string LastName { get; set; }

            public virtual ushort Age { get; set; } = (ushort)0;

            public virtual string Gender { get; set; }

            public virtual bool Male
            {
                get { return Gender == "M"; }
                set { Gender = value == true ? "M" : default; }
            }

            public virtual bool Female
            {
                get { return Gender == "F"; }
                set { Gender = value == true ? "F" : default; }
            }

            public virtual bool Valid
            {
                get { return System.Linq.Enumerable.Contains(Student._validValues, Gender); }
            }

            public override string ToString()
            {
                return this.Stringify();
            }
        }
    }
}
                Back
                
using System.Threading;
using System.Threading.Tasks;

namespace Cobol
{
    public interface IStudents
    {
        Task<IStudent> Process(CancellationToken cancellationToken);
    }
}
                Back
                

Contact

:
Under construction...

Menu