Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 22:25 12 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Chain Command

Author Message
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 06:47pm 09 Mar 2013
Copy link to clipboard 
Print this post

If you're chaining programs and using a pointer to keep track of what programs to run from your menu or master program, don't initialise the pointer in the master program - it will get overwritten.

Chaining looks like a really useful feature.

James

Here's a short example:

' a program to show how the Chain command can be used.
' We rely on MMBasic initialising numeric variables to 0.
' Each chained program increments the value of counter
' that tracks where we are up to.
' If we initialised the counter to 0 in code, it will continually
' get reset and overwrite the values updated by the chained programs.

? "UpTo counter is:"; UpTo

If UpTo = 0 then

[2 lines added]
OPTION Base 1 ' must be set before any DIM statements
False = 0 : True = 1 ' if done here, only performed once.

CHAIN "Chain0.bas"

ElseIf UpTo = 1 then
CHAIN "Chain1.bas"

Elseif UpTo = 2 then
CHAIN "Chain2.bas"

Else
? "Finished"
endif


' Chain0.bas

? "In Chain0.bas"
UpTo = UpTo + 1
CHAIN "chn-demo.bas" ' back to calling program
END


' Chain1.bas

? "In Chain1.bas"
UpTo = UpTo + 1
CHAIN "chn-demo.bas" ' back to calling program
END


' Chain2.bas

? "In Chain2.bas"
UpTo = UpTo + 1
CHAIN "chn-demo.bas" ' back to calling program
END


[added] Also, some things can only be run once, and must be run before other commands, like Option Base 1 must be declared before any dimensioning is done.

For efficiency, some things should only be done once, like setting False = 0.
If you set variables, declare option base, etc, in the program at the top of the chain, do it after the test for the first run (see added lines in the first code example).Edited by James_From_Canb 2013-03-11
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3308
Posted: 12:13pm 10 Mar 2013
Copy link to clipboard 
Print this post

A neat solution but why would you want to keep chaining back to the first program? Each module could chain direct to the next module as you can use chain an unlimited number of times.

I can see that you would need to return to a main program if it held a menu that was used to select the module that ran next. But then you would not need a counter as the menu entry would select the module.

Geoff
Geoff Graham - http://geoffg.net
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 05:47pm 10 Mar 2013
Copy link to clipboard 
Print this post

  Geoffg said   A neat solution but why would you want to keep chaining back to the first program?
Geoff

A good question with a couple of answers.
I was taught to program in hierarchies and it's a habit now.
I was converting large chunks of code and it made testing easier if I could enable and disable modules quickly from a single control program.
It was working out how to implement 'include' code, where a file of code is executed and the program has to work out where to return to in the calling program.
And it was an interesting issue to look at.

James

My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 05:34pm 22 Mar 2013
Copy link to clipboard 
Print this post

Two more points about chaining:

You need to provide the program name as a string i.e. chain "nextprog.bas", whereas the rest of MMBasic no longer needs the quote marks around the program name.

A program that is chained to it has its own MM.CMDLINE$, but you can't pass parameters to a program you're chaining to.

For example:

ParamsIn$ = MM.CMDLINE$
CHAIN "nextprog.bas" ParamsIn$ and CHAIN "nextprog.bas ParamsIn$" don't work.

This means the program chained to always has an empty MM.CMDLINE$.

You cannot use the chained program like a black box function called by multiple programs and controlled by command line parameters. It's easy enough to work around though. The chained program needs to be modified to work with a saved copy of the original MM.CMDLINE$ (like ParamsIn$ above).

Anyway, they're both trivial really - but noting them, especially the second point, might save someone else the trouble of working them out by trial and error like I did.

And I reckon the chain command it the best thing since sliced bread.

James

My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 05:46pm 23 Mar 2013
Copy link to clipboard 
Print this post

One thing that occurs to me with Chaining is that the Chained-to program cops all the baggage (variables) from the chaining program. This can be a problem if you want to chain two programs originally developed as stand alone applications, such as Renumber and Format. One really needs to vacate much of the space used by the Chaining program.

Wouldn't it be nice if you could pass only the variables the chained program needed so that you had the whole memory space available in the Chained-to program. Granted, you could individually ERASE array variables that are not needed to recover space but you don't have that option with other variables. You could also pass the variables needed via a file.
e.g.

CHAIN filename[.bas] [variable] [,variable]... [,#Filenumber] [,#Filenumber]...

If the filename is followed by a list of variables and files, then all the others in the chaining program are deleted and closed. If the list is absent then all are carried forward as at present.

(Sorry Geoff... more work, if you think it worth while!! :-) )

Cheers,
Hugh
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 11:26am 02 Apr 2013
Copy link to clipboard 
Print this post

I've emailed Geoff with a possible bug involving Chaining. At least there's an easy workaround.

If you read data values in a program and then chain to another, the pointer that keeps track of the data values isn't being cleared when the second program starts.

The consequence is that the second program does not start reading the data values from the beginning of the first line of data in the second program.

If that sounded a little convoluted, here's the example code I sent Geoff to demonstrate the issue.

' this program demonstrates a possible bug in the chain command.
' The pointer that tracks the next DATA element to be read
' causes unexpected results when the CHAIN command is used.
'
DIM ARR1$(6)
DATA "Data1", "Data2", "Data3", "Data4", "Data5", "Data6"

For i = 1 to 4 ' only 4 of the 6 in this test
Read ARR1$(i)
PRINT "Main program saved value "; ARR1$(i)
next i

CHAIN "TestChn.bas"


And TestChn.bas is

' Part 2 of a program to demonstrate a potential bug with the CHAIN command.
'
DIM ARR2$(6)
DATA "P2Data1", "P2Data2", "P2Data3", "P2Data4", "P2Data5", "P2Data6"

For i = 1 to 6
Read ARR2$(i)
PRINT "Chained program saved value "; ARR2$(i)
next i

END


TestChn.bas reads in P2Data5 and P2Data6 then gives an error because there is no more data to read.

It gives a similar error if the first program reads in all 6 data values.

The workaround is to use the RESTORE statement at the start of the second program. This resets the pointer.

James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
djuqa

Guru

Joined: 23/11/2011
Location: Australia
Posts: 447
Posted: 11:47am 02 Apr 2013
Copy link to clipboard 
Print this post

Why depend on embedded DATA values when you should be reading the values from a DATA file.
If the program is complex/ big enough to need to be chained in sections, then data statements would be had to justify.Edited by djuqa 2013-04-03
VK4MU MicroController Units

 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 12:40pm 02 Apr 2013
Copy link to clipboard 
Print this post

  djuqa said   Why depend on embedded DATA values when you should be reading the values from a DATA file.
If the program is complex/ big enough to need to be chained in sections, then data statements would be had to justify.


Ah! The problem arose when chaining to an existing program. James_From_Canb and I have been working on Chaining his Renumber program to my Format. Both programs use DATA statements internally for their own purposes. The Data from Renumber's DATA statements is not used by Format.

Cheers,
Hugh
 
djuqa

Guru

Joined: 23/11/2011
Location: Australia
Posts: 447
Posted: 12:45pm 02 Apr 2013
Copy link to clipboard 
Print this post

Suppose it is my programming background (I learned assembly,pascal,c before I learned BASIC), but I have never seen the need/advantage/usage of DATA statements
VK4MU MicroController Units

 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 02:39pm 02 Apr 2013
Copy link to clipboard 
Print this post

  djuqa said   Suppose it is my programming background (I learned assembly,pascal,c before I learned BASIC), but I have never seen the need/advantage/usage of DATA statements

You ought to try it some time. It's a very convenient way of providing a program with a small amount of constant data and it has the advantage of making the program self-contained (doesn't depend upon the presence of an external data file).

However, I have to agree with you that it is better to use a file if the data is volatile or if there is a lot of it.

In Format I use data statements to provide a list of Operators and Basic Commands that Format needs to parse a line of code. There are only a small number (12 out of 201) commands which affect formatting and only 9 operators to check so it makes sense to load the Command$() and Operator$() arrays from DATA statements.

On the other hand, in Crunch that I am developing, I need to be able to check against all 201 commands so I load them from a Data file.

Cheers,
Hugh
 
djuqa

Guru

Joined: 23/11/2011
Location: Australia
Posts: 447
Posted: 02:49pm 02 Apr 2013
Copy link to clipboard 
Print this post

  shoebuckle said  
You ought to try it some time.
Cheers,
Hugh


Not likely, It goes against all my experience,training and good MVC (Model,View,Controller i.e. Separation of CODE/Data) programming practice.
But each to their own techniques.

Edited by djuqa 2013-04-04
VK4MU MicroController Units

 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 03:23pm 02 Apr 2013
Copy link to clipboard 
Print this post

They're Constants.

Think of it like object oriented coding where each object (in this case a program or subroutine) contains the non-volatile data it will need.

[ducks for cover and fits flame-proof suit].

James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
djuqa

Guru

Joined: 23/11/2011
Location: Australia
Posts: 447
Posted: 03:36pm 02 Apr 2013
Copy link to clipboard 
Print this post

No comment (puts the Petrol tin and matches back in the Shed)


VK4MU MicroController Units

 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 04:51pm 02 Apr 2013
Copy link to clipboard 
Print this post

I seem to recall that Pascal has a type Constant which was used for setting fixed values just like a Data statement.
 
Lopezjm2001

Regular Member

Joined: 08/07/2012
Location: Australia
Posts: 42
Posted: 04:34am 24 May 2013
Copy link to clipboard 
Print this post

Hi all and Geoff Graham,

I am using the CHAIN command with three files. The starting file is AUTO.BAS which will chain to either F5.BAS or F6.BAS depending on whether you press the F5 keyboard button or the F6 keyboard button.

You start by typing:

new [enter]
load "AUTO.BAS" [enter]
run [enter]
t

The t button allows the AUTO.BAS program to run as there is no CAN connected.

The programs work fine after pressing the F5 or F6 button the first time but the second time no matter which button I press F5 or F6 I get this error:

"Too many nested DO or WHILE loops"

It seems that once a file is chained the mmbasic interpreter does not reset the number of loops. I am wondering whether it is a bug in the basic interpreter?

Anyhow I have uploaded the three files. The files are lengthy.

2013-05-24_143142_CHAIN.zip

Thanks,

John Lopez

Edited by Lopezjm2001 2013-05-25
Lopez
 
James_From_Canb

Senior Member

Joined: 19/06/2011
Location: Australia
Posts: 265
Posted: 06:15pm 29 May 2013
Copy link to clipboard 
Print this post

John,

Just to clarify, AUTO.BAS runs and chains to F5.BAS or F6.BAS, and these two programs run AUTORUN.BAS to get back?

I'm ignoring the obvious problem that the original program is called auto.bas, not autorun.bas.

Regards

James
My mind is aglow with whirling, transient nodes of thought careening through a cosmic vapor of invention.

Hedley Lamarr, Blazing Saddles (1974)
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3308
Posted: 05:40am 31 May 2013
Copy link to clipboard 
Print this post

Damn, another bug
I will fix it in the next version.

Geoff
Geoff Graham - http://geoffg.net
 
shoebuckle
Senior Member

Joined: 21/01/2012
Location: Australia
Posts: 189
Posted: 03:46pm 01 Jun 2013
Copy link to clipboard 
Print this post

James_From_Canb, smart fellow that he is, pointed out a feature of MMBasic which is useful if you are having to Chain programs because you run out of memory. This is most likely to happen when using large string arrays and lots of string variables.

It is most likely that you don't need many of these variables in the Chained-to program, and sometimes bugs can creep in because you use the same variable name in both programs and forget that it already contains data. Array variables are easy to remove using the ERASE command but all global variables carry across.

The significant word here is "Global". Local variables do not carry across so James' suggestion is to make all but a short stub of the Chaining program a "Main" subroutine and define all the variables, including arrays, that you do NOT want to be carried forward to the Chained program as Local within Sub Main.

Here is an example. Program Chain1.bas chains to Chain2.bas. Only variables Fname$, a, i, d$ and the array d(i) carry across and you will see that trying to print array variable e(1) in Chain2.bas causes an error because it hasn't come across and therefore hasn't been DIM'd.

A very simple, neat solution. Thanks James.
Hugh


'Chain1.bas
Fname$="Chain2.bas"
a=10
Dim d(a)
for i=1 to a
d(i)=i
next
i=1
Main(a)
Chain Fname$
End

Sub Main(c)
Local b,c$,e(c),i
for i=1 to c
e(i)=i
Next
c=c+2
b=c
C$="Now is the time"
d$=c$
End Sub


'Chain2.bas
Print "Fname$=",Fname$
Print "a=",a
Print "b=",b
Print "c=",c
Print "c$=",c$
Print "d$=",d$
Print "i=",i
Print "Array d=";
For j=1 to 10
Print d(j);
Next
Print
For j=1 to 10
Print e(j)
Next
Edited by shoebuckle 2013-06-03
 
Tinine
Guru

Joined: 30/03/2016
Location: United Kingdom
Posts: 1646
Posted: 02:17pm 21 May 2019
Copy link to clipboard 
Print this post

Chain? Does this still exist? I don't see it in the manual.
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1672
Posted: 02:34pm 21 May 2019
Copy link to clipboard 
Print this post

Hi,
I think it refers to MAXIMITES only.
This thread is from 2013!

Regards
Michael
causality ≠ correlation ≠ coincidence
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025