Create Demo Application Using Lazarus for Android

I created this video for myself showing the basic steps for creating a very simple Android program using Lazarus.

I am the intended audience and the intended audience cares about the content not the video quality, so don’t expect it to be pretty. BUT, if you want to see how simple it is to create an Android app in Lazarus, and can’t find another video with much detail (I wasn’t able), then you are welcome to have a look.

Posted in c-lazarus | Tagged , | 5 Comments

COBOLWorx GnuCOBOL and Debugger

The next step in delving back into COBOL is to get a working debugger. While using DISPLAY debug lines was the only debugging I had available when I did this for a living, there should be no reason to have to do that these days!

After going thru the gnuCOBOL FAQ, I found there is a way to make use of the GNU Debugger (gdb). Unfortunately the link to the debugger in the FAQ is dead. After a little digging I found cobcd, the COBOL debugger pre-processor  on the COBOLWorx site.

I spent quite some time getting cobcd to ‘make’. This is because if you want to run it on Windows you must compile using MinGW/MSYS2 and I have been using the older MSYS.

Even after I got it to compile under MSYS2, it failed to work with Arnold Trembley’s version of the gnuCOBOL I’ve been using. After several days of hair pulling, I finally decided to contact COBOLWorx directly. Bob from COBOLWorx responded quickly and confirmed that cobcd doesn’t play well with Anold Trembley’s version of gnuCOBOL.

Download and Install COBOLWorx GnuCOBOL and the Cobc Pre-Processor

If you are using Windows, the easiest way to get the cobcd pre-processor to work is to download the COBOLWorx’s Windows version of the compiler and debugger. In fact, their build of the compiler is so easy to install, I’d recommending using it even if you aren’t planning to use the cobcd debugger.

The download page for the COBOLWorx versions of gnuCOBOL is here.

Instead of messing with MinGW, I just downloaded the self-extracting installer for Windows found at the top of this page.

If, for some reason, the above link fails, the copy I downloaded is here. However, expect this  version to go out of date quickly.

Once you have the self-extracting EXE file downloaded, double-click on it and let it install. The program is a bit slow to install.

I installed the compiler into the default c:\gnucobol directory.

As the install completes you will see this dialog box:

I recommend you say yes and let it add these environment variables. Beats having to mess with the environment when you want to run the compiler.

Now reboot the PC to make sure everything gets setup properly.

Dealing with Microsoft Python

To test the install, type cobcd and you should see:

C:\cobol>cobcd
This is the cobc debugging wrapper [Version 3.17]
Use it as you would 'cobc'
C:\cobol>

If you instead only get a DOS prompt and no version information, chances are the MicroSoft Python is before gnuCOBOL’s python in your path. The following change will correct this problem.

Microsoft decided to put a stub program into your WindowsApps directory that does nothing except invoke the Microsoft Store. This breaks cobcd. Correcting the problem involves putting the gnuCOBOL path ahead of WindowsApps.

If you look at the path for your user, you will find WindowsApps is searched before gnucobol:

Simply move gnucobol above windowsapps:

The Test Program

Before using the debugger, we need a program to compile. Here is a sample program I’ll be using:

       >>source free
identification division.
program-id.
    testgdb.

data division.
working-storage section.

01  dst-rec.
    03  lastname                        pic x(20).
    03  firstname                       pic x(20).
    03  birthdate                       pic 999999.
    03  age                             pic zz9. 
    03  salary                          pic $$$$,$$9.99.

01  kount                               pic s9(4), comp.

01  src-rec.
    03  lastname                        pic x(20),          value "SMITH".
    03  firstname                       pic x(20),          value "JOHN".
    03  birthdate                       pic 999999,         value 800715.
    03  age                             pic s9(4), comp,    value 35.
    03  salary                          pic s9(6)v99, comp-3, value 123456.78.

procedure division.

    move "TEST"                         to lastname of dst-rec.
    move 20                             to age      of dst-rec.
    move 50000                          to salary   of dst-rec.

    perform varying kount from 1 by 1 until kount > 10,
        add 1                           to age of src-rec;
        end-perform.

    move corresponding src-rec          to dst-rec.

    display "dst-rec:".
    display dst-rec.

    stop run.

Setting Up GDB

The first time you attempt to run GDB, you will get a warning:

C:\cobol>gdb -q testgdb.exe
Reading symbols from optfde01.exe...
warning: File "C:\cobol\optfde01-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
        add-auto-load-safe-path C:\cobol\optfde01-gdb.py
line to your configuration file "C:\Users\me/.gdbinit".
To completely disable this security protection add
        set auto-load safe-path /
line to your configuration file "C:\Users\me/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
        info "(gdb)Auto-loading safe path"
(gdb)

To fix this, we need to add set auto-load safe-path / to the file .gdbinit.

It easy enough to create c:\users\<username>\.gdbinit with the proper contents:

C:\Users\me>type \users\me\.gdbinit
set auto-load safe-path /

Compiling the Test Program

Here is an example of compiling the program with debugging and running it w/o invoking the debugger:

C:\cobol\gdbDebugging>cobcd -x testgdb.cbl
C:\cobol\gdbDebugging>testgdb.exe
dst-rec:
SMITH               JOHN                800715 45$123,456.78

C:\cobol\gdbDebugging>

Setting the Initial Breakpoint

To invoke the debugger (-q omits printing the header):

C:\cobol\gdbDebugging>gdb -q testgdb.exe
Reading symbols from testgdb.exe...
registering CPrint (Usage is "print  ") [Version 3.17]
registering CWatch (Usage is "cwatch ")
(gdb)

If you start execution of the program, it will run what I assume is part of the run-time library. I’ve found the best way to bypass this code is to manually set a breakpoint on the first executable line.

First use the search command to find the procedure division and then list to see the lines around it:

(gdb) search procedure
25      procedure division.
(gdb) l
20          03  firstname                       pic x(20),          value "JOHN".
21          03  birthdate                       pic 999999,         value 800715.
22          03  age                             pic s9(4), comp,    value 35.
23          03  salary                          pic s9(6)v99, comp-3, value 123456.78.
24
25      procedure division.
26
27          move "TEST"                         to lastname of dst-rec.
28          move 20                             to age      of dst-rec.
29          move 50000                          to salary   of dst-rec.

Line 27 is the first executable line, so set a breakpoint there and use continue to let the program run until it hits the breakpoint:

gdb) break 27
Breakpoint 1 at 0x4016e3: file testgdb.cbl, line 27.
(gdb) run
Starting program: C:\cobol\gdbDebugging\testgdb.exe
[New Thread 5136.0xc98]
[New Thread 5136.0x18a8]
[New Thread 5136.0x16e8]

Thread 1 hit Breakpoint 1, testgdb_ (entry=0) at testgdb.cbl:27
27          move "TEST"                         to lastname of dst-rec.
(gdb)

Use Continue to Execute Until Next Breakpoing

Once the program is executing, you use continue, rather than start, to execute code until the next breakpoint is encountered:

(gdb) break 28
Breakpoint 2 at 0x401713: file testgdb.cbl, line 28.
(gdb) continue
Continuing.

Thread 1 hit Breakpoint 2, testgdb_ (entry=0) at testgdb.cbl:28
28          move 20                             to age      of dst-rec.
(gdb)

Using Step and Next

Step executes the next line and stop, but if a procedure is called, it will stop inside of the called procedure.

Next executes the next line without stopping inside of any called procedures. This is typically what I want to have happen.

After you type either, simply pressing enter will execute the command again (this is true of any command).

(gdb) next
29          move 50000                          to salary   of dst-rec.
(gdb)<cr>
31          perform varying kount from 1 by 1 until kount > 10,
(gdb)

Examining Contents of Variables

Typing p* will display all variables:

(gdb) p*
 1 : 01 dst-rec/testgdb [W-S] : "TEST", ' ' , "000000 20 $50,000.00"
 2 : 03 lastname/dst-rec/testgdb [W-S] : "TEST                "
 3 : 03 firstname/dst-rec/testgdb [W-S] : "                    "
 4 : 03 birthdate/dst-rec/testgdb [W-S] : "000000"
 5 : 03 age/dst-rec/testgdb [W-S] :  20
 6 : 03 salary/dst-rec/testgdb [W-S] :  $50,000.00
 7 : 01 kount/testgdb [W-S] : +0000
 8 : 01 src-rec/testgdb [W-S] : [534d495448", 20 , 4a4f484e", 20 , 3830303731350023012345678c]
 9 : 03 lastname/src-rec/testgdb [W-S] : "SMITH               "
10 : 03 firstname/src-rec/testgdb [W-S] : "JOHN                "
11 : 03 birthdate/src-rec/testgdb [W-S] : "800715"
12 : 03 age/src-rec/testgdb [W-S] : +0035
13 : 03 salary/src-rec/testgdb [W-S] : [012345678c]

To see the value of only kount, type:

(gdb) p kount
01 kount/testgdb [W-S]  :  +0000

I don’t make a practice of using MOVE CORRESPONDING so I don’t normally need to qualify variables with OF, but I wanted to see how they work in the debugger. To see the value of LASTNAME OF SRC-REC:

(gdb) p lastname/src-rec
03 lastname/src-rec/testgdb [W-S]  :  "SMITH               "

Using cwatch to Display Variable When It Changes

Here I ‘watch’ the value of kount change in the PERFORM loop. Every time the value changes, the program pauses execution:

(gdb) l
26
27          move "TEST"                         to lastname of dst-rec.
28          move 20                             to age      of dst-rec.
29          move 50000                          to salary   of dst-rec.
30
31          perform varying kount from 1 by 1 until kount > 10,
32              add 1                           to age of src-rec;
33              end-perform.
34
35          move corresponding src-rec          to dst-rec.
(gdb) break 35
Breakpoint 3 at 0x40189d: file testgdb.cbl, line 35.
(gdb) cwatch kount
Hardware watchpoint 4: *(char(*)[2])(0x406060)

(gdb) continue
Continuing.

Thread 1 hit Hardware watchpoint 4: *(char(*)[2])(0x406060)

Old value = "\000"
New value = "\000\001"
0x630cf909 in ?? () from c:\gnucobol\bin\libcob-4.dll
(gdb)<cr>
Continuing.

Thread 1 hit Hardware watchpoint 4: *(char(*)[2])(0x406060)

Old value = "\000\001"
New value = "\000\002"
0x0040188a in cob_addswp_s16 (val=, p=0x406060 ) at testgdb.cbl:32
32              add 1                           to age of src-rec;
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x004016e3 in testgdb_ at testgdb.cbl:27
        breakpoint already hit 1 time
2       breakpoint     keep y   0x00401713 in testgdb_ at testgdb.cbl:28
        breakpoint already hit 1 time
3       breakpoint     keep y   0x0040189d in testgdb_ at testgdb.cbl:35
4       hw watchpoint  keep y              *(char(*)[2])(0x406060)
        breakpoint already hit 2 times
(gdb) disable 4
(gdb) continue
Continuing.

Thread 1 hit Breakpoint 3, testgdb_ (entry=0) at testgdb.cbl:35
35          move corresponding src-rec          to dst-rec.
(gdb)

Finally, let the MOVE CORRESPONDING execute and compare records:

gdb) n
37          display "dst-rec:".
(gdb) p *
 1 : 01 dst-rec/testgdb [W-S] : "SMITH               JOHN                800715 45$123,456.78"
 2 : 03 lastname/dst-rec/testgdb [W-S] : "SMITH               "
 3 : 03 firstname/dst-rec/testgdb [W-S] : "JOHN                "
 4 : 03 birthdate/dst-rec/testgdb [W-S] : "800715"
 5 : 03 age/dst-rec/testgdb [W-S] :  45
 6 : 03 salary/dst-rec/testgdb [W-S] : $123,456.78
 7 : 01 kount/testgdb [W-S] : +0011
 8 : 01 src-rec/testgdb [W-S] : [534d495448", 20 , 4a4f484e", 20 , 383030373135002d012345678c]
 9 : 03 lastname/src-rec/testgdb [W-S] : "SMITH               "
10 : 03 firstname/src-rec/testgdb [W-S] : "JOHN                "
11 : 03 birthdate/src-rec/testgdb [W-S] : "800715"
12 : 03 age/src-rec/testgdb [W-S] : +0045
13 : 03 salary/src-rec/testgdb [W-S] : [012345678c]
(gdb) c
Continuing.
dst-rec:
SMITH JOHN 800715 45$123,456.78
[Thread 8156.0x11d8 exited with code 0]
[Thread 8156.0xf14 exited with code 0]
[Thread 8156.0x96c exited with code 0]
[Inferior 1 (process 8156) exited normally]
(gdb)

There you go, gdb for gnuCOBOL. Pretty slick!

Posted in c-gnuCOBOL | Tagged , | Leave a comment

Debugging GnuCOBOL Using WITH DEBUGGING MODE

Prior to COBOL85, COBOL had its own debug module accessed in the DECLARATIVES. This was removed in the 1985 standard. It appears gnuCOBOL still supports the older debugging, but given gdb can be used (next blog post), I won’t go down that route.

Instead, I will examine the debugging that COBOL85 does still natively support.

Debugging Lines

When debugging is enabled, lines with a D in column 7 (fixed format) or start with >>D (free format) are compiled. If not enabled, they are not compiled.

>>D display "debugging line hit".

OR

      D    display "debugging line hit".

Normally one indicates these lines should be compiled using by specifying WITH DEBUGGING MODE in the SOURCE-COMPUTER paragraph:

source-computer. 
    x86                                 with debugging mode.

However, you can leave this clause off, and use the -fdebugging-line switch when invoking the compiler.

Here is code and a sample run using debugging statements:

C:\cobol\oldDebugging>cobc -t- -fdebugging-line -xj sw0debug.cbl
GnuCOBOL 3.1-rc1.0      sw0debug.cbl         Mon Aug 31 15:31:40 2020  Page 0001

LINE    PG/LN  A...B............................................................

000001         >>source free
000002  identification division.
000003  program-id.
000004      test.
000005
000006  environment division.
000007  configuration section.
000008  source-computer.
000009      x86.
000010
000011  procedure division.
000012
000013  >>D display "debugging line hit".
000014      display "non debugging line hit".
000015
000016      stop run.


0 warnings in compilation group
0 errors in compilation group
debugging line hit
non debugging line hit

Using SW0 to Control Debugging

When I was writing COBOL on the HP3000, I almost always wanted my debugging lines compiled. If there was a problem, I didn’t want to have to recompile code. This was probably because minicomputers were so slow and compilers took so many resources, each programmer might be lucky to get in 3 compiles a day. I often worked nights just so I wouldn’t have to fight as much for compile time!

I needed a simple mechanism to enable/disable debugging at run time rather than compile time. There were several ways to do this on the HP3000 and I did it using the switch register with SPECIAL-NAMES of SW0 and I see gnuCOBOL supports a switch register as well.

The first HP3000 I programmed (Series III) had an actual 16 bit switch register on the front panel that primarily was used to enter a start address to boot the system. However, it could also be read programmatically by COBOL.

The switch register went away on later models, but there needed to be a way to continue to support programs that made use of that register. On the HP3000, this was done by passing the value of the 16 bit switch register, in decimal, to the program in the PARM keyword such as:

:RUN MYPROG;PARM=1

This would set bit 0 of the switch register to 1 rather than 0. (PARM=2 would have set switch register bit 1 to 1). Thus, when I ran a COBOL program on the HP3000 with PARM=1, it would display debugging so I would not have to recompile.

Here is the modified program that uses the SWITCH-0 register in special names to create the condition-name called fl-debug which is tested to determine is debugging output should be displayed. Since SWITCH-0 has not yet been set fl-debug will return false and the debugging will not be displayed:

C:\cobol\oldDebugging>cobc -t- -xj sw0debug.cbl
GnuCOBOL 3.1-rc1.0      sw0debug.cbl         Mon Aug 31 16:09:01 2020  Page 0001

LINE    PG/LN  A...B............................................................

000001         >>source free
000002  identification division.
000003  program-id.
000004      test.
000005
000006  environment division.
000007  configuration section.
000008  source-computer.
000009      x86                                 with debugging mode.
000010  special-names.
000011      SWITCH-0                            is fl-debug-flag,
000012          on status                       is fl-debug.
000013
000014  procedure division.
000015
000016  >>D if fl-debug,
000017  >>D     display "debugging line hit".
000018
000019      display "non debugging line hit".
000020
000021      stop run.


0 warnings in compilation group
0 errors in compilation group
non debugging line hit

For gnuCOBOL, the SWITCH-0 register is set to 1 by setting an environment variable:

C:\cobol\oldDebugging>set COB_SWITCH_0=on

C:\cobol\oldDebugging>sw0debug.exe
debugging line hit
non debugging line hit

Setting COB_SWITCH_0 to off will disable the debugging.

Next time I’ll discuss using gdb with gnuCOBOL. Compared to using a modern debugger like gdb, having only DISPLAY is pretty primitive, but can still work. I still have to debug MCU code just using printf or even worse, just flashing a LED.

Posted in c-gnuCOBOL | Tagged | Leave a comment

Calling Pascal procedures to Manipulate the GnuCOBOL String Data Structure

Last episode saw the definition of a string data structure for COBOL. This episode will show how to write Pascal Code to manipulate the string data structure (cst-string).

Using these examples, it would be easy enough to implement any needed string processing procedure.

I have created 3 Pascal procedures: cstset, cstdeb, and cstrightj.

cstset is used to initialize cst-string by moving text from a buffer into cst-string and setting the cst-len appropriately. It replaces the COBOL-only code I did in the prior post.

cstdeb (deblank) will remove leading and trailing spaces from cst-string.

cstrightj (right justify) will right justify the text in cst-string using the specified field width.

To make using these procedures easier, there is a copy book (.cpy file) for each call: cfCstSet, cfCstDeb, and cfCstRightJ.

Rather than describe all of the parts, the following file contains a listing of the Pascal program, commands to compile and execute the Pascal and COBOL code with the resulting run’s output, and finally the compiler’s listing of the COBOL code.

All Listings

 

Posted in c-gnuCOBOL | Tagged , | Leave a comment

A String Data Structure for GnuCOBOL

When I started to learn COBOL in the late 70’s, HP BASIC was my primary language. BASIC is adept at handling strings. As I quickly found, COBOL (particularly the 1968 standard I was using), was not.

I know there are some string processing functions available in gnuCOBOL such as TRIM. For this post, I want to implement the string data structure I used for all of my string processing needs.

Simple Example of Lack of Strings

Here is a very rudimentary example of a problem that occurs by not having some type of string data structure. Say you define 2 variables:

01  buffer                     pic x(40).
01  formattedAmount            pic ---,--9.99.

Then initialize and output them:

move "JOHN SMITH"             to buffer.
move 1.98                     to formattedAmount.

display ">", buffer, "|", formattedAmount, "<".

The display would show:

>JOHN SMITH                              |      1.98<

Lining up data in columns might be suitable for a line printer but is ugly on a terminal. If you want to see the output as

>JOHN SMITH|1.98<

it really wasn’t doable.

A COBOL String Data Structure

At my first job, on a DEC-10, I stumbled upon a simple way to control how much of a string buffer could be displayed:

01 len                           pic s9(4), comp.
01 str.
   03  str-byte                  pic x,
         occurs                  0 to 80 times,
         depending on            len.

To display str without trailing spaces, I just needed to:

move 80                         to len.
move "JOHN SMITH"               to str.
move 10                         to len.
display ">", str, "<".

>JOHN SMITH<

Having to move 80 to len first was a bit clumsy. In more careful reading of the manual I found I could create the following data structure which became my standard COBOL string data structure:

01  cst-string.
    03  cst-max                            pic s9(4), comp, value 80.
    03  cst-len                            pic s9(4), comp.
    03  cst-in                             pic x(80).
    03  cst-out redefines                  cst-in.
        05  cst-byte                       pic x,
                occurs                     0 to 80 times,
                depending on               cst-len.

This worked like a charm. Now to setup a string it just required this:

move "JOHN SMITH"                         to str-in.
move 10                                   to str-len.
display ">", str-out, "<".

When I moved to a job programming HP3000’s in COBOL, I took this idea with me where I used it for several decades. More than likely some of that code is still running.

If you are a COBOL programmer, you may be saying “WHOA, you can’t do that!” Per the COBOL standards, you cannot redefine a variable length field!

That is true in gnuCOBOL and is true according to the ’74 and ’85 standard manuals I have. BUT it did work on the DEC10 and the HP3000 COBOL compilers.

Making the COBOL String Structure Work for gnuCOBOL

I screwed around with trying to get past that limitation for a while and finally gave up. Instead gnuCOBOL requires this data structure:

01  cst-string.
    03  cst-max                                   binary-short unsigned, value 256.
    03  cst-len                                   binary-short unsigned.
    03  cst-out.
        05 cst-byte                               pic x,
             occurs                               0 to 256 times,
             depending on                         cst-len.

The downside to this structure is you cannot move a string to it without first setting cst-len to cst-max before initializing cst-out. So to create a string you would do this:

move cst-max                                     to cst-len.
move "JOHN SMITH"                                to cst-out.
compute cst-len = 
    function length( 
        function trim( cst-out, trailing)).
if cst-len = 1 and cst-byte(1) = space then
    move zero                                    to cst-len.

Still kind of a lot of work to do, but one can create a copy book code fragment to do the work:

       >>source free
*>cfCstSet:
*>  01/31/12:   DWH.                 
*>              Created for openCOBOL.            
*>  08/15/20:   DWH.
*>              Updated for gnuCOBOL.
                                                                  
*>--------------------------------------------------------------   
*>    COPY cfstrset
*>    REPLACING cst-in BY <literal|word>].                           
*>--------------------------------------------------------------   
                                                                  
*>    openCOBOL doesn't allow my old STR string structure. The new
*>    structure requires the following code frag to move something
*>    into the structure and set the size.

*>    This code fragment can be copied anywhere such as:
*>        if 1=1 then
*>            copy cfCstSet replacing cst-in with "test";
*>        else,
*>            next sentence.
                             
    move cst-max                        to cst-len;
    move cst-in                         to cst-out;
    compute cst-len = 
        function length( 
            function trim( cst-out, trailing));
    if cst-len = 1 and cst-byte(1) = space then
        move zero                      to cst-len;
    end-if;

Now, to move create a string of “JOHN SMITH”, I just:

copy cfcstset,
    replacing cst-in by "JOHN SMITH".

Here is a listing of an example program (with expanded copy books) so you can see everything:

GnuCOBOL 3.1-rc1.0      cfcstsetEx.cbl       Sun Aug 16 15:21:34 2020  Page 0001
000011
LINE    PG/LN  A...B............................................................
000013
000001         >>SOURCE FREE
000002  identification division.                by "JOHN SMITH".
000003  program-id.urce free
000004      cfcstsetEx.
000005
000006  data division.  
000007
000008  working-storage section.
000009
000010  copy wscst.
000001C        >>SOURCE FREE
000002C *>wscst
000003C *>    AA0000: 01/08/88:    DWH.
000004C *>            STR COBOL string routine data names.
000005C *>    AA0001: 01/31/12:    DWH.
000006C *>            Converted to run in OpenCobol.                                   
000007C
000008C *>--------------------------------------------------------------
000009C *>    COPY wscst
000010C *>    [REPLACING 256 BY ].
000011C *>--------------------------------------------------------------ng
000012C *>    into the structure and set the size.
000013C *>    STANDARD COBOL STRING DATA STRUCTURE.
000014C *>    You can change the maximum string size by using the
000015C *>    REPLACING clause.
000016C *>            copy cfCstSet replacing cst-in with "test";
000017C 01  cst-string.
000018C     03  cst-max                         binary-short unsigned, value 256
000018+ .
000019C     03  cst-len                         binary-short unsigned.
000020C     03  cst-out.MITH" to cst-out;
000021C         05  cst-byte                    pic x,
000022C            occurs                       0 to 256 times,
000023C            depending on                 cst-len.
000024C
000011
000012  procedure division.
000013
000014      copy cfCstSet
000015          replacing cst-in                by "JOHN SMITH".
000001C        >>source free
000002C *>cfCstSet:
000003C *>  01/31/12:   DWH.
000004C *>              Created for openCOBOL.
000005C *>  08/15/20:   DWH.
000006C *>              Updated for gnuCOBOL.
000007C
000008C *>--------------------------------------------------------------
000009C *>    COPY cfstrset
000010C *>    REPLACING cst-in BY <literal|word>].
000011C *>--------------------------------------------------------------
000012C
GnuCOBOL 3.1-rc1.0      cfcstsetEx.cbl       Sun Aug 16 15:21:34 2020  Page 0002

LINE    PG/LN  A...B............................................................

000013C *>    openCOBOL doesn't allow my old STR string structure. The new
000014C *>    structure requires the following code frag to move something
000015C *>    into the structure and set the size.
000016C
000017C *>    This code fragment can be copied anywhere such as:
000018C *>        if 1=1 then
000019C *>            copy cfCstSet replacing cst-in with "test";
000020C *>        else,
000021C *>            next sentence.
000022C
000023C     move cst-max                        to cst-len;
000024C     move "JOHN SMITH" to cst-out;
000025C     compute cst-len =
000026C         function length(
000027C             function trim( cst-out, trailing));
000028C     if cst-len = 1 and cst-byte(1) = space then
000029C         move zero                      to cst-len;
000030C     end-if;
000031C
000032C
000016
000017      display ">", cst-out, "<".
000018
000019      stop run.


0 warnings in compilation group
0 errors in compilation group

And the resulting output:

>JOHN SMITH<

Next time, I will show how to pass the COBOL string data structure to Pascal and let it do some basic string processing functions.

Posted in c-gnuCOBOL | Tagged | Leave a comment

Parameter Passing when calling Free Pascal from GnuCOBOL

In our last exciting episode of gnuCOBOL, I showed the rudiments of calling a Pascal program from COBOL. Today I will delve deeper into passing parameters.

Example Code

Rather than put a lot of code straight into this post, here are links to a COBOL program and Pascal procedures that perform many different types of calls:

The Primary COBOL program.

The Primary Pascal routines.

The output to this program is:

calling Pascal
Hello World!
@proc0
@proc1. p1: 1
@proc2. p1: 1; p2: 2
@func1. p1: 1
@procbyref. p1: 1; p2: 2
func1 returned: +0002
@procrec: memory dump of rec:
0000: 534D 4954 4820 2020 2020 2020 2020 2020 2020 2020 SMITH
0014: 2020 2020 2020 2020 2020 4A4F 484E 2020 2020 2020 JOHN
0028: 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020
003C: 0026 0001 2345 678C .&..#Eg.
called Pascal

Matching Data Types

By default, COBOL does a pretty good job of hiding underlying data types. It is meant to be a machine dependent language and it does a great job of it where data types are concerned.

If I want a 4 digit number I use PIC 9999. If it might be negative, then I use PIC S9999. If I will be doing a lot of computations with it then I say PIC S9999, COMP. I never have to think about which type of integer I need.

You can call Pascal directly with variables defined using PIC clauses, but it sometimes it takes some trial and error. To pass numbers to Pascal you are better off using gnuCOBOL’s numeric usage defintions. In the GnuCOBOL 2.2 Nov 2017 manual, these can be found in section 9.8.3 such as:

So rather than

01  mydataP                        pic s9(4), comp.

use

01  mydataI                       binary-short signed.

Here are a couple of the more esoteric issues one could have when converting from COBOL PIC to numeric usage types: size errors and implied decimal points.

Size Errors

There can be a problem with mixing PIC variables and usage type variables. Moving the above mydataI to mydataP can cause leading digit truncation.

For example, if mydataI contains 12345 (it can contain up to 32767) and is moved to the 4 digit mydataP field, mydataP will contain 2345, not 12345.

If you must move mydataI to mydataP do so using compute like this:

compute mydataP = mydataI,
    on size error,
        display "Overflow occurred!!".

A sample program showing the various types of moves between these two data types can be seen here.

The output from this program:

After p(1234) to i move:
p: +1234
i: +01234
After i(9876) to p move:
i: +09876
p: +9876
After i(12345) to p move:
i: +12345
p: +2345
Trying compute:
Overflow occurred!!

Implied decimal point

There are several reasons I like COBOL and one is that it handles dollar & cents so easily with perfect precision. One should NEVER put dollar amounts into a floating point data type regardless of the language! That leaves (in most lanaguages) just integers. That means the programmer is responsible for knowing that

salary: integer;

must contain pennies. The programmer is responsible for knowing where the decimal point is at. If he wants more precision than pennies then he is responsible for that as well. Addition/subtraction is hard enough, but multiplication and division are even more cumbersome.

In Pascal, if  I want to put $1000 into salary I must use 10,000 pennies:

salary := 100000;

In COBOL, you define salary as:

77  Salary      PIC S9(6)v99, comp.

The compiler determines the correct underlying data type to use. Note that ‘v’ means that is where an implied decimal point is located. When you say:

move 1000 to salary.

you get a Salary of $1000.00 as you would expect.

If you must pass salary to a Pascal program you either need to determine the underlying data type used, or move it to a numeric usage field.

s9(6)v99 contains 7 digits which will fit in a 32bit integer just fine so I can use

01  salaryP                     pic s9(6)v99.
01  salaryI                     usage binary-int signed.

In this test program, I move salaryP to salaryI and call a Pascal routine to simply display it.

The COBOL code

The Pascal Code

When run, the output is:

size of salaryI: 4
size of salaryP: 4
Passing salaryP(+123456.78) to prtSalary:
@prtSalary. Salary: 12345678
Passing salaryI(+0000123456) to prtSalary:
@prtSalary. Salary: 123456

There is a REALLY IMPORTANT side effect highlighted above!!

After moving salaryP to salaryI, the fractional part of salaryP is lost:

move 123456.78 to salaryP.
move salaryP to salaryI.

As seen in the program output above, salaryI contains 123456 after the move NOT 12345678.  To retain the fractional part you would  need to compute rather than move:

compute salaryI = salaryP * 100.

This would result in salaryI of 12345678 being passed to prtSalary.

It seems to me, when mixing variables defined using PIC COMP and moving them to/from numeric usage variables you want to use COMPUTE and NOT MOVE.

In the real world, I can’t ever recall wanting to pass dollar amounts to a non-COBOL subroutine. COBOL excels at handling dollar amounts, so use it instead!

Endian Issues

When I initially did this testing and write-up, I didn’t realize there were endian issues until the first time I passed an integer to pascal and found it was garbage.

When using PIC S9(n), COMP, gnuCOBOL stores and passes the field as big-endian in keeping with the format of old mainframe storage formats.

When you pass that field to Pascal as an integer, it will expect it to be in little-endian format. The value isn’t so the pascal routine receives what amounts to garbage.

In summary, using COMP or BINARY for gnuCOBOL results in big-endian variables. Using BINARY-SHORT or other BINARY- formats will result in little-endian variables. So, make sure you use the BINARY- numeric usage clause on any integer that will be passed to an external Pascal routine.

At this time, there is an explanation in the gnuCOBOL FAQ here.

Matching Parameter Passing Methods

Back when I was coding in HP’s COBOL85, there was only one way to pass variables to the outside world: BY REFERENCE. GnuCOBOL allows by reference, by value, and by contents (see section 9.6.1.1 of the gnuCOBOL manual).

Because by reference was the only way you once could pass parameters, I would have expected that to be the default, but I have found in these test programs you must specify how to pass each parameter.

call "procrec",
    using       by reference    test-rec,
                by value        function byte-length(test-rec).

Dealing with Function Returns

gnuCOBOL the ability to receive integers from Pascal functions.

Thus, if you want to return a numerical value in a Pascal function, do so using this type of definition:

function func: integer;

You would call func in this manner:

01  i-long                    binary-long signed.

call "func"
    returning                 i-long.

I have been able to return long and short integers in this manner.

Here is some example code:

COBOL Program

Pascal Routines

The results of the program were:

Value of returned in i-long: +0123456789
Value of returned in i-short: +12345
Calling func w/o a return:
done

Returning Omitted

If COBOL calls a Pascal function, but the functional result is not used, then you must use omitted:

call "func"
    returning omitted.

I found that if you left the “returning omitted” clause off, the linker would not find the external “func” probably because the parameters didn’t match up properly.

Passing COBOL Records

The primary test COBOL program at the top of this blog entry contains a record to be passed to Pascal defined as:

01  test-rec.
    03   lastname                           pic x(30).
    03   firstname                          pic x(30).
    03   age                                pic s9(4), comp.
    03   salary                             pic s9(9)v99, comp-3.

Calling the pascal program is simple:

call "procrec",
    using                           by reference test-rec,
                                    by value     function byte-length(test-rec).

In the Pascal procedure, there are 2 ways to handle the incoming test-rec. If I need to get to every field I would define a Pascal record to do so along the lines of:

Type
  recT                    = record
    lastname              : packed array of char[1..30];
    firstname             : packed array of char[1..30];
    age                   : smallint;
    salary                : ??
    end;

OK, off the top of my head, I don’t know exactly how large this COMP-3 field is in Pascal, I’d have to look it up, but I’m just going to represent the record as an array of bytes so I use:

type 
    aobT                                = array of byte;

procedure procrec(
    var rec                             : aobT;
    reclen                              : integer
    );

In this sample program, I just want to dump the entire record, not read any specific fields, so an array of bytes works just fine. When I dump this record I find I have:

0000: 534D 4954 4820 2020 2020 2020 2020 2020 2020 2020 SMITH
0014: 2020 2020 2020 2020 2020 4A4F 484E 2020 2020 2020 JOHN
0028: 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020
003C: 0026 0001 2345 678C .&..#Eg.

I can also see from this dump that the comp-3 field takes 6 bytes or 12 nibbles (each digit and the sign takes a nibble).

Strings

I have been slowly working toward strings as that is my primary interest in calling Pascal routines. I have a very large Pascal string processing library that would be nice to access. That will be covered in my next post.

Posted in c-gnuCOBOL | Tagged , | Leave a comment

Calling Free Pascal Procedures from GnuCOBOL in Windows

I’m slowly working through various experiments with gnuCOBOL. One experiment is to call Pascal code from a gnuCOBOL program. The gnuCOBOL FAQ has an example, but I presume this only works for Linux. It definitely doesn’t work for MinGW/Windows.

I spent entirely too much time trying to get this experiment to work; thus, the blog post. I don’t want to forget how to do this.

The sample Pascal program (pascalCode.pas):

library pascalCode;
{$mode objfpc}{$H+}

procedure testp;
begin
writeln('Hello World!');
end;

procedure zippy;
begin
writeln('zippy');
end; // zippy

exports
    testp,
    zippy;

begin
end.

Here is the COBOL program(test.cbl):

       >>SOURCE FREE
identification division.
program-id.
    test.

procedure division.

0000-mainline.

    display "calling Pascal".
    call "testp",
        returning omitted.
    call "zippy",
        returning omitted.
    display "called Pascal".

0099-exit.

    stop run.

To compile and run:

export COB_PRE_LOAD=pascalCode
fpc pascalCode.pas
cobc -x test.cbl -L. -l:pascalCode.dll
./test

and the results:

./test
calling Pascal
Hello World!
zippy
called Pascal

 

Posted in c-gnuCOBOL | Tagged , | Leave a comment

Installing gnuCOBOL into MinGW

I’ve been away from this project for several months and managed to forget exactly how I was supposed to invoke the COBOL compiler. I had made a note in the post
Installing gnuCOBOL on Windows, but that just tells where to find the compiler, not how to incorporate it into minGW.

I decided to incorporate gnuCOBOL into minGW again and document it for future use.

Download the Compiler

You can find the latest MinGW version at Arnold Trembley’s website. I want the version:

(NEW) GnuCOBOL 3.1-rc1 (30JUN2020) MinGW compiler for Windows XP/7/8/10 with COBOL ReportWriter. Includes VBISAM 2.0.1 for Indexed Sequential file access support, GMP 6.2.0, and PDCurses 4.1.99 (17.0 megabytes). Rename .7z to .exe for self-extracting archive.

If this website goes away, the above file (which will go out of date quickly) can also be found here.

Install the Compiler

I assume you have already installed MinGW. My notes on doing so can be found here.

Arnold Trembley’s version of gnuCOBOL is configured to reside at c:\mingw\share. Therefore, create the directory c:\mingw\share, and unzip the contects of the gnuCOBOL zip file into it.

Add C:\MinGW\share\gnucobol\bin to your path.

This almost is done. There is one problem yet: the path will be setup to run GCC out of /mingw/bin and that will cause a problem (mingw’s gcc compiler will be unable to find <libcobol.h>. You need to run it out of /mingw/share/gnucobol/bin.

To do this you must edit /etc/profile and insert /mingw/share/gnucobol/bin as shown:

# My decision to add a . to the PATH and as the first item in the path list
# is to mimick the Win32 method of finding executables.
#
# I filter the PATH value setting in order to get ready for self hosting the
# MSYS runtime and wanting different paths searched first for files.
if [ $MSYSTEM == MINGW32 ]; then
export PATH=".:/mingw/share/gnucobol/bin:/usr/local/bin:/mingw/bin:/bin:$PATH"
else
export PATH=".:/usr/local/bin:/bin:/mingw/bin:$PATH"
fi

To Test

Start minGW bash and type cobc -v

chiefdude10/~:cobc -v cobc (GnuCOBOL) 3.1-rc1.0
Built Jul 04 2020 17:17:54 Packaged Jul 01 2020 00:39:30 UTC
C version (MinGW) "6.3.0"
loading standard configuration file 'default.conf'
cobc: error: no input files
chiefdude10/~:

You should see the bold line above, indicating that the default configuration is loaded.

The same will work in CMD:

C:\>cobc -v
cobc (GnuCOBOL) 3.1-rc1.0
Built Jul 04 2020 17:17:54 Packaged Jul 01 2020 00:39:30 UTC
C version (MinGW) "6.3.0"
loading standard configuration file 'default.conf'
cobc: error: no input files

C:\>

You now have a working gnuCOBOL compiler!

To test, I created the following file (there are 7 spaces before ‘>>SOURCE FREE’):

       >>SOURCE FREE
*> Sample COBOL program
IDENTIFICATION DIVISION.
PROGRAM-ID. hello.
DATA DIVISION.
PROCEDURE DIVISION.
DISPLAY "Hello, world!".
STOP RUN.

To compile and run:

C:\cobol\helloworld>cobc -x helloW.cob

C:\cobol\helloworld>helloW
Hello, world!

 

Posted in c-gnuCOBOL | Tagged , | Leave a comment

Portable Air Conditioner Adapter for Casement Window

I’ve lived in this house for many years and every summer, for about a month, the bedroom is just too hot to sleep in until well past bed time. Though I have central A/C, the ducting was designed for heat only and the central A/C has never been very effective upstairs.

The bedroom has just 2 skinny casement windows. I’ve looked at skinny A/C units, but none of them are skinny enough. I’ve looked at portable A/C units, but I could never come up with an acceptable venting option.

This spring I saw portable A/C units for sale at Costco and the question came up again. This time I put the right search criteria into DuckDuckGo and found a guy that had cut a piece of plexiglass the size of his screen. He then cut a hole in the plexiglass to allow for the vent:

Genius! I had been trying to work out a way to build a wedge-shaped device that the window could close down on.

After going thru various reviews, I ended up purchasing this Black & Decker model BPACT08WT. The price was right, it would cool my bedroom, and it wasn’t overkill (I don’t like stressing the wiring of this 80 year old house).

Coming up with a flange to connect the hose to the wood screen adapter was another challenge. The black and decker A/C unit uses a 5″ hose, so I ordered two difference 5″ flanges and hose clamps on amazon. When they showed up I found the flanges were exactly 5″ as well. There was no way to get the hose over the flange short of cutting it and I just didn’t like that idea.

After more research I found this flange on Amazon:

At $27.99, way more expensive than the other flanges but this offer louvers plus threads to mate to the tubing. When the flange showed up it fit properly so I was ready to begin building the full adapter. Interestingly, the flange is 3D printed.

Using the screen as a template, I cut the proper size out of a half sheet of 1/4″ plywood. Using a compass and some of the scrap, I test cut a 5.5″ hole with a jig saw and a fine blade. The flange fit properly, and  I was confident I could cut a fairly round hole in the actual project.

Once the wood was cut, the edges smoothed with a router’s 1/8″ round-over bit, and everything sanded, I primed and painted it with matching semi-gloss paint.

For final assembly, I cut out a bit of screen I had laying around and found 3 nylon bolts to fasten the flange to the wood.

The white rectangle right of the bolts is paraffin. I rubbed that onto the flange where it would come in contact with the wood. I also rubbed it around the perimeter of the finished wood. This will prevent the paint from sticking to the flange or the old woodwork in the window.

Here is the finished adapter ready to be installed:

Here is the final install:

Posted in c-Misc | Tagged , | Leave a comment

Installing MinGW (for gnuCOBOL)

As I started researching how to install the gnuCOBOL SQL preprocessor, I found that there are no binaries (Windows or Linux). If I’m going to move forward, I’m going to have to be able to  compile the preprocessor.

One option is to take a step backwards and redo what I’ve done so far on Linux. But for no particularly good reason, I want to do this project on Windows. That means getting gcc running under Windows. Cue minGW.

For what seems like 20 years, I’ve been using unxutils to provide Unix based commands in Windows which allows me to move between Windows and Linux seamlessly. BUT unxutils just provides some basic utilities, it doesn’t provide the ability to compile and run C programs on Windows.

One option is the new Windows Subsystem for Linux (WSL). I have multiple issues with this – it requires Windows 10 64bit, is a full blown Linux install, and it is Microsoft. I’m looking for simple, small, and clean. That is not typical of Microsoft. OK, I have an attitude.

The other options are MinGW or cygwin. gnuCOBOL for Windows is compiled on MinGW and the preprocessor seems to have no preference, so I will install MinGW and see how it goes.

The plus side to MinGW is it will replace my old unxutils and provide the same features plus provide bash on top of Windows.

MinGW Installation

Considering the general complexity of what is being installed, the installation is amazingly simple. You download an installer which works much like the Linux Synaptic Manager. From there you select which parts of MinGW you want to install.

The installer is found at https://sourceforge.net/projects/mingw/files/Installer/

Once started, I selected the default options (installing into c:\MinGW). Once the installer is setup, it asks which parts of MinGW you want to install. I selected mingw32-base (gcc), and msys-base (bash + utilities):

Before attempting to run anything, edit the file C:\MinGW\msys\1.0\etc\fstab. It
must contain:

# Win32_Path                           Mount_Point
#------------------------------------- -----------
C:/MinGW                               /mingw
C:/                                    /c

C:/ is important because it allows bash access to the entire hard drive, otherwise you will only have access to the c:\mingw\msys\1.0 directory.

Next, in C:\MinGW\msys\1.0, copy a link of msys.bat to Start Menu, named bash, so bash can be run from the start menu.

At this point, you can double click on the msys.bat (bash) link and bash will start.

Finally, add c:\mingw\msys\1.0\bin to your path. When done, commands such as ls can be run from cmd.

Installing Other Packages

There are some other packages that I know I would want. These can be installed directly using mingw-get:

mingw-get install msys-vim
mingw-get install msys-wget

Some Operational Notes

You can start bash from inside cmd like this:

bash -l

-l means to run login scripts.

To run a script with bash, you run bash and specify the path as you would inside bash. For example, if I want to run c:\tmp\test.sh, use:

bash -l -c /c/tmp/test.sh

You may or may not want -l. I have an extensive login script that I always want run.

Using scp (or pscp) requires a slightly screwy path as well.

scp myfile /tmp

will work fine.

scp myfile myhost:/tmp

will fail with ssh: Could not resolve hostname myhost;c: No such host is known.

I don’t fully understand what is going on, but myhost:/tmp is not being translated correctly. To get it to work you need two //:

scp myfile myhost://tmp

I have found that I can copy the entire MinGW environment between machines by simply copying c:\MinGW and adding the path.

Conclusion

I’m looking forward to further experiments with MinGW. I don’t have to write many cmd BAT files any more but when I do I just detest them. They are so clunky compared to bash. I would be perfectly happy migrating everything to bash.

Posted in c-gnuCOBOL | Tagged , | Leave a comment