Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 19:54 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 : bug in print/?

Author Message
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2464
Posted: 04:17am 28 Mar 2019
Copy link to clipboard 
Print this post

while investigating palcal's problem, i found a bug in the way ? is handled. enter the folowing exactly into mmbasic's internal editor:

a$="hello"
?a$ " world"

End


press f2 to run, and the output will be

hello world


now edit the program and you'll see that ?a$ " world" has been expanded to Printa$ " world", which when saved (if you edit the program elsewhere) and run again generates an error.

this is with mmbasic 5.05.01 on an mx170.


essentially, when ? is expanded to Print a space should be added afterwards by the editor's save routine if there is not already one there.


cheers,
rob :-)
Edited by robert.rozee 2019-03-29
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1646
Posted: 06:31am 28 Mar 2019
Copy link to clipboard 
Print this post

I tried that little program in DOS MMBasic and got the same result as you. It would run again and again without error. So I tried with 5.05.01 on an mx170 and got the same result. Did it again using MMEdit - same result. Then I tried:

a$="hello"
?a$ " world"

printa$ " world"
End


and got:

hello world
[4] printa$ " world"
Error: Unknown command
>


list
a$="hello"
Printa$ " world"

printa$ " world"
End


So it doesn't mind when it creates the PRINT with no space after but not if I do it. Weird.

I think you've found a bug and it's also there in DOS MMBasic.

Bill
Keep safe. Live long and prosper.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 08:20am 28 Mar 2019
Copy link to clipboard 
Print this post

This is a perfect example of why it is better not to compromise syntax to make things easier for users.

? without a space was a special case Geoff allowed that was really only intended for immediate usage at the command line.

The diagnosis of the above results is as follows:

? and print are the same command.
When a program is loaded commands are converted into single byte tokens
When you edit tokens are converted back to normal text
At this point the print token becomes PRINT not ?
If the original program didn't have a space after ? then now we don't have a space after PRINT
printa$ isn't a valid command but printa$= would be as in this case printa$ would be a valid variable

SOLUTION: DON'T USE ? WITHOUT A SPACE EXCEPT AT THE COMMAND LINEEdited by matherp 2019-03-29
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2464
Posted: 11:56am 28 Mar 2019
Copy link to clipboard 
Print this post

but does this mean that every instance of:

Print "something"

is encoded with an 'inert' space character after the print token? the example of using the shorthand form, ?, demonstrates how the space contributes nothing to the interpreter running the program, however it is essential to converting from plain text to the tokenized form.

and if the space character is inert/superfluous here, is it equally superfluous after most other statements: Input, GoTo, Let, Dim, to name but a few. all these spaces add up to make a significant contribution to the flash space taken up by any large mmbasic program, as well as slowing down execution. the space characters are a bit like NOP instructions sprinkled liberally throughout the code.

it seems a better strategy when tokenizing and detokenizing would be for statement tokens to represent the keyword followed by a space, just as (i assume) function tokens currently represent the keyword followed by an opening round bracket.

geoff or peter: is it easy for a basic program to locate the starting address where a basic program is stored in flash and to then loop through memory printing out the stored program so we can easily examine this? i'm thinking of writing something stored in the library to carry out the task.


cheers,
rob :-)
Edited by robert.rozee 2019-03-29
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 02:01pm 28 Mar 2019
Copy link to clipboard 
Print this post

  matherp said  
SOLUTION: DON'T USE ? WITHOUT A SPACE EXCEPT AT THE COMMAND LINE

No! it is just a little bug that can be fixed easily.
Microblocks. Build with logic.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 05:10pm 28 Mar 2019
Copy link to clipboard 
Print this post

  Quote  is it easy for a basic program to locate the starting address where a basic program is stored in flash


very, just use PEEK(PROGMEM, offset)

  Quote  it seems a better strategy when tokenizing and detokenizing would be for statement tokens to represent the keyword followed by a space


Isn't hindsight wonderful I don't know the guts of MMBasic well enough to comment properly but I suspect this would be a big change == new bugs

  Quote  No! it is just a little bug that can be fixed easily.


That is for Geoff to decide. However, whether easy or not it is a special case and the more special cases in code the more difficult to maintain it becomes. The bug exists because of a special case.

// first test if it is a print shortcut char (?) - this needs special treatment
if(*p == '?') {
match_i = GetCommandValue("Print") - C_BASETOKEN;
match_p = p + 1;
} else {
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1646
Posted: 09:28pm 28 Mar 2019
Copy link to clipboard 
Print this post

  MatherP said  ? and print are the same command.
When a program is loaded commands are converted into single byte tokens
When you edit tokens are converted back to normal text
At this point the print token becomes PRINT not ?
If the original program didn't have a space after ? then now we don't have a space after PRINT
printa$ isn't a valid command but printa$= would be as in this case printa$ would be a valid variable

SOLUTION: DON'T USE ? WITHOUT A SPACE EXCEPT AT THE COMMAND LINE


Shouldn't the interpreter force that? The manual say's nothing about not needing a space whether or not it's on the command line.

A "special case" is an inconsistency. If it confuses people like Rob and causes a discussion like this, what chance does a simple user like me have of knowing what's going on?

My tuppence worth.

Bill
Keep safe. Live long and prosper.
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2464
Posted: 01:08pm 29 Mar 2019
Copy link to clipboard 
Print this post

  matherp said  just use PEEK(PROGMEM, offset)


cool! i've just written a small program to do this, below is the output, with source code interspersed:

i=0
<1>[253][234][159]i[198]0<0>

<1>[253][234]<0>
Do
<1>[253][234][132]<0>
j=Peek(progmem, i)
<1>[253][234][159]j[198][208]progmem, i)<0>
If j>127 Then
<1>[253][234] [156] j[197]127 [177]<0>
Print "[" Str$(J) "]";
<1>[253][234] [166] "[" [164]J) "]";<0>
Else If j<32 Then
<1>[253][234] [134] j[196]32 [177]<0>
Print "<" Str$(J) ">";
<1>[253][234] [166] "<" [164]J) ">";<0>
Else
<1>[253][234] [136]<0>
Print Chr$(j);
<1>[253][234] [166] [134]j);<0>
EndIf
<1>[253][234] [142]<0>
i=i+1
<1>[253][234] [159]i[198]i[186]1<0>
Loop Until i=200
<1>[253][234][162] [179] i[198]200<0>
<0><0>
[255][255][255][255][255]...



it looks like every line starts with the three byte prefix <1><253><234>. and every line ends with a <0>. statements have the expected [bad] superflous trailing space, while functions have the opening bracket omitted.

oddly, maths operators are encoded into new tokens, which seems odd to me - it is a waste of tokens. any operator character not contained in a literal string can always be interpreted as a token without needing to have it converted to a new token. i guess the rationale is to simplify the token detection logic (just needing to check for the high bit set).


comments? geoff, what does the three-byte preamble mean? it seems a tad wasteful if it is always the same three-byte sequence.


cheers,
rob :-)
Edited by robert.rozee 2019-03-30
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10572
Posted: 02:12pm 29 Mar 2019
Copy link to clipboard 
Print this post

  Quote  what does the three-byte preamble mean?


It is the default when no line number is included

#define T_CMDEND 0 // flags used in the program lines
#define T_LINENBR 1
#define T_LABEL 2
#define MAXLINENBR 65001 // maximim acceptable line number
#define NOLINENBR (MAXLINENBR + 1) // dummy line number to indicate that a line number has not been used
//
if(isdigit(*tp) && i < 8) { // if it a digit and not an 8 digit hex number (ie, it is CFUNCTION data) then try for a line number
i = strtol(tp, &tp, 10);
if(i <= 0 || i >= MAXLINENBR) i = NOLINENBR;
*op++ = T_LINENBR;
*op++ = (i>>8);
*op++ = (i & 0xff);
p = tp;
} else if(!console) {
*op++ = T_LINENBR;
*op++ = (NOLINENBR>>8);
*op++ = (NOLINENBR & 0xff);
}
Edited by matherp 2019-03-31
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2464
Posted: 03:38pm 29 Mar 2019
Copy link to clipboard 
Print this post

that seems horribly inefficient, especially considering that line numbers
are rarely used these days. it would be far more efficient to use as the
first byte of every line:
<0> = end of line marker (ie, is a blank line)
<1> = a 2-byte line number follows, then the rest of the basic line
<2> = a label followed by colon, then rest of the basic line
<3> = custom function body
else the contents of a basic line.

this would mean that for regular lines of basic code, there would be no
preamble. for custom function body there would be a 1-byte preamble. for
a line with a line number there would be a 3-byte preamble. for a line with
a label there would be 2 bytes + the number of characters in the label.

in this way 3 bytes per line would be saved, as for the vast majority of
lines there would be no preamble required. for a 1000 line program this would
save around 3k of flash space, about half of what is required to include
double-precision maths on an mx170 if i am not mistaken!


cheers,
rob :-)
Edited by robert.rozee 2019-03-31
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3308
Posted: 09:09am 31 Mar 2019
Copy link to clipboard 
Print this post

Yes, the three bytes at the start of each line are rather inefficient and are a hang over from when line numbers were in common use.

I have had this issue on my todo list for a long time and it is the fear of causing a new set of of bugs that has caused it to remain there for so long. As an example, some time ago (in Ver 5.04.06) I standardised some of the code dealing with the line prefix (as a preliminary step towards removing these bytes) but it caused a great many odd bugs in quite a few versions after.

Rather than seeing this as an issue of simply saving some bytes of flash, it should be seen as a trade off between that and reliability. There are so many users using MMBasic for real critical tasks that I am resultant to foist on them something that may have some hidden nasty bugs.

Given the complexity of the interpreter and the fact that this change will affect many aspects of it, bugs are to be expected and cannot be avoided, no matter how much care is taken. The real issue is how to test and find these bugs. I have a lot of test programs but given that this is a programming language there are an almost infinite number of ways that commands can be strung together so not all bugs can be caught. Releasing beta test versions is another method of finding bugs but it is unfair to rely too much on users falling over bugs.

All this hand wring does not escape the fact that this is something that needs to be changed, however I plan to do it in a series of small steps. In doing it I will also incorporate Rob's excellent idea of implying a space after every command token (probably this will be another fertile source of bugs).

Geoff

BTW I have just returned from a long trip overseas but will have to leave again almost immediately to see my mum who is seriously ill. As a result you will not hear much from me over the next couple of months.
Geoff Graham - http://geoffg.net
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 09:22am 31 Mar 2019
Copy link to clipboard 
Print this post

Sorry to hear that Geoff. I wish you and your mother the best!
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2171
Posted: 10:36am 31 Mar 2019
Copy link to clipboard 
Print this post

wishing the best for your mum. Stay safe
 
Paul_L
Guru

Joined: 03/03/2016
Location: United States
Posts: 769
Posted: 05:15am 01 Apr 2019
Copy link to clipboard 
Print this post

My best wishes to you and your mother! Take care of yourself while you're taking care of her.

Paul in NY
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1427
Posted: 03:53pm 01 Apr 2019
Copy link to clipboard 
Print this post

Your mother will be in my thoughts. I'm hoping for the best for you and her.
Micromites and Maximites! - Beginning Maximite
 
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