Step-by-step debugger for Clarion. Is anyone interested?

I have never been comfortable debugging code using VID. Like other developers, I use stop, message, and procedures to view the contents of queue and group, as well as debugView. However, this is not effective for debugging application code. Therefore, around 2008, a specialized step-by-step debugger was developed for our projects. It works well with my code, and I now use it regularly for debugging code in routines and class methods. I don’t know how interesting this approach is for other developers, but I haven’t seen anything like this discussed. The idea was simple. We copy the original clw file to a clws file, which is then used for navigating through the code and restoring the original code after debugging. In the routines or class methods being debugged, we insert a call to the debugging procedure at the line level. This way, the debugger includes a class , few simple window procedures in Clarion and procedures for preparing the code for debugging. We do not need to compile the application in debug mode.

After preparation, the code looks like this.
In the data section of the procedure, we declare an instance of the class.

                     MEMBER('fsorepsF.clw')       ! Это модуль типа MEMBER
CompareKnProd PROCEDURE

FsDebugIntLor &FsDebugInt  !ОТЛ. Объявление класса

In the code section, we initialize the class and store references to variables.

CODE
   FsDebugIntLor &= new(FsDebugInt)
   FsDebugIntLor.Init('D:\claproects11\fsopt\fsOptRepsF\fsorepsF061.clw','D:\claproects11\fsopt\fsOptRepsF\fsorepsF061.clws')
   FsDebugIntLor.AddProc('Proc',134,1)
   FsDebugIntLor.AddVar('loc:saveavto',loc:saveavto,1,0)
   FsDebugIntLor.AddVar('loc:fsentrycodeflag',loc:fsentrycodeflag,1,0)
   FsDebugIntLor.AddGroup('loc:groupparam',loc:groupparam,1,0)
   FsDebugIntLor.AddTableGl('fsparotch',fsparotch)
   FsDebugIntLor.AddTableGl('klients',klients)
   FsDebuger(address(FsDebugIntLor),135,1,0)

This is how the code looks in the debugging area.

   loop lor:i=1 to records(lor:queue)
   FsDebuger(address(FsDebugIntLor),893,1,1)
      get(lor:queue,lor:i)
   FsDebuger(address(FsDebugIntLor),894,1,1)
      if lor:numKor<>''
   FsDebuger(address(FsDebugIntLor),895,1,1)
         lor:num=lor:numKor
   FsDebuger(address(FsDebugIntLor),896,1,1)
      .
   FsDebuger(address(FsDebugIntLor),897,1,1)
      lor:p1=instring('/',lor:inn,1,1)
   FsDebuger(address(FsDebugIntLor),898,1,1)
      if lor:p1>0
   FsDebuger(address(FsDebugIntLor),899,1,1)
         lor:kpp=left(sub(lor:inn,lor:p1+1,20))
   FsDebuger(address(FsDebugIntLor),900,1,1)
         if lor:kpp='0'
   FsDebuger(address(FsDebugIntLor),901,1,1)
            lor:kpp=''
   FsDebuger(address(FsDebugIntLor),902,1,1)
         .
   FsDebuger(address(FsDebugIntLor),903,1,1)
         lor:inn=left(sub(lor:inn,1,lor:p1-1))
   FsDebuger(address(FsDebugIntLor),904,1,1)
      .

We compile app. The debugger window looks like this.

The debugger has the following features.

  1. Step-by-step execution of code.
  2. Setting simple and conditional (any expression) breakpoints. Executing code between breakpoints.
  3. Viewing the values of variables in a selected line of source code.
  4. Selecting variables, groups, queues, and tables for monitoring.
  5. Viewing the contents of groups, queues, and table buffers.
  6. Viewing the results of dynamic expressions.
  7. Changing the values of variables during debugging.
  8. Viewing standard values (errorcode, error, and so on).
  9. Searching for line fragments in the source code and working with bookmarks.
  10. Saving a list for monitoring between debugging sessions.
  11. Remote debugging on the client side without interrupting user operations.

I’d be curious to see a demonstration.
Maybe you could contact @John_Hickey and show something on ClarionLive?

That looks quite interesting,
Can you please explain some of the arguments

I’m wondering if the code would be easier to maintain by using ASSERT(0, SomeEquate) and take advantage of SYSTEM{PROP:AssertHook2} = ADDRESS( SomeFunction) as the Assert will automatically give you the module name and line number

I am also interested in a demo

looks like something I would be interested in a demo of also

904 - the line number in the source code.
1 - the number of the procedure (class method)
1 - routine number in a procedure (class method)

Parameters 3 and 4 are used to determine the values of variables declared in procedures and routines when we retrieve them from the context of a code line.

I made a small mp4 video on a real project with explanations in English.

https://finsoftrz.ru/mp4/debug2025.mp4