Discussion:
how to use a sysvar in Basic
(too old to reply)
Jim Nagel
2018-09-04 15:20:34 UTC
Permalink
I'm working on a wee Basic program and at one stage I need to compare
mystring$ to a system variable websiteroot$dir.

This system variable is set in an external obeyfile which contains
only one line -- set websiteroot$dir <obey$dir>
-- in other words, the sysvar contains a path to a directory.

In my Basic program, lines like this work with no problem:
headfile$ = "<websiteroot$dir>.fefi.fofum.head"
mytail% = OPENIN "<websiteroot$dir>.fefi.fofum.tail"

But this line produces an error "Unknown or missing variable":
PRINT websiteroot$dir
Same error whether or not I use anglebrackets <websiteroot$dir>.

Leads me to think there's something fundamental I need to understand
about the use of sysvars within Basic. Web search brought up various
articles and PRM references but nothing seemed to the point. Can
anyone enlighten me, please?

Must I convert the contents of <websiteroot$dir> to a conventional
Basic string? Is there an existing elegant way of doing so?
Otherwise, I'll see where I can go from this within Basic:
*show websiteroot$dir { > tempfile }

(Don't know where I ever found that "{ > xyz }" business. Found no
mention in the new User Guide or online, probably not easy to index.
I vaguely remembered it from some dark mental crevice and played with
spaces etc until, surprise, it worked. What's it called?)
--
Jim Nagel www.archivemag.co.uk
"From" address is genuine but will change. Website has current one.
|| See you at the show? www.wakefieldshow.org.uk April 21
Steve Drain
2018-09-04 17:00:30 UTC
Permalink
Post by Jim Nagel
I'm working on a wee Basic program and at one stage I need to compare
mystring$ to a system variable websiteroot$dir.
Must I convert the contents of <websiteroot$dir> to a conventional
Basic string?
Yes.
Post by Jim Nagel
Is there an existing elegant way of doing so?
PRINT FNval("websiteroot$dir")

END

DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$

There is no check that it is a string, so a little more effort is needed
for a general routine.

In Basalt you can do:

PRINT SYS("websiteroot$dir")
Jim Nagel
2018-09-04 17:54:28 UTC
Permalink
Post by Steve Drain
Post by Jim Nagel
Is there an existing elegant way of doing so?
PRINT FNval("websiteroot$dir")
END
DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$
Elegant indeed! Thanks, Steve. Does the trick painlessly.
Post by Steve Drain
There is no check that it is a string, so a little more effort is needed
for a general routine.
PRINT SYS("websiteroot$dir")
I'll look into that anon. But for the present purpose I'm cooking.
--
Jim Nagel www.archivemag.co.uk
Post by Steve Drain
Post by Jim Nagel
"From" address is genuine but will change. Website has current one.
|| See you at the show? www.riscoslondonshow.co.uk Oct 27
Julian Fry
2018-09-08 20:03:01 UTC
Permalink
Post by Jim Nagel
Post by Steve Drain
Post by Jim Nagel
Is there an existing elegant way of doing so?
PRINT FNval("websiteroot$dir")
END
DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$
Elegant indeed! Thanks, Steve. Does the trick painlessly.
Agreed. Using OS_ReadVarVal is the obvious call to use but there is
another which I would appreciate comments on - validity, performance,
problems, etc. It is:

DIM buff% 256
SYS "OS_GSTrans","<websiteroot$dir>",buff%,256 TO n%,,l%
IF l%>0 THEN PRINT LEFT$($buff%,l%) ELSE PRINT "Not set"
--
Best wishes

Julian Fry

---
This email has been checked for viruses by AVG.
https://www.avg.com
Jim Nagel
2018-09-05 16:13:20 UTC
Permalink
Post by Steve Drain
[Jim wrote:] Must I convert the contents of <websiteroot$dir> to a
conventional Basic string?
Yes.
Is there an existing elegant way of doing so?
PRINT FNval("websiteroot$dir")
END
DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$
There is no check that it is a string, so a little more effort is needed
for a general routine.
PRINT SYS("websiteroot$dir")
Thanks again, Steve. I have now downloaded and had a play with
Basalt. Nice.

Found another problem in my particular situation: the sysvar whose
value I want to put into an ordinary Basic string variable ...
DOES NOT EXIST! As I found by running my Basic app immediately after
a fresh boot. I had forgotten the sysvar is set by something in my
ordinary boot system. Which clearly means the sysvar would not exist
on somebody else's system if I were to distribute the program.

Before trying Basalt, in ordinary Basic I tried v$="phoney" in
SYS"OS_ReadVarVal",v$,END,-1 TO je%,v$
because the spec said that a negative value (-1 here) will test
whether my sysvar (v$) exists and return an error if the answer is no.
(I'm not sure about the stuff after TO; I imitated a previous line.)

Well, it indeed produced a nice RiscOS error box. Wimplog says:
00000124: Error from (unknown): System variable 'phoney' not
found

It would be more useful for my present purpose if, instead of that
error message, I could make the function return some arbitrary value
(such as "") and exit. I tried PRINT ERR -- nothing was printed.
Any suggestions?

The Stronghelp for Basalt keyword SYS says similarly:
There will be error "Unknown or missing named variable" if
the system variable is not found.
--
Jim Nagel www.archivemag.co.uk
Post by Steve Drain
"From" address is genuine but will change. Website has current one.
|| See you at the show? www.riscoslondonshow.co.uk Oct 27
Matthew Phillips
2018-09-05 19:19:19 UTC
Permalink
Post by Jim Nagel
Post by Steve Drain
[Jim wrote:] Must I convert the contents of <websiteroot$dir> to a
conventional Basic string?
Yes.
Is there an existing elegant way of doing so?
PRINT FNval("websiteroot$dir")
END
DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$
There is no check that it is a string, so a little more effort is needed
for a general routine.
PRINT SYS("websiteroot$dir")
Thanks again, Steve. I have now downloaded and had a play with
Basalt. Nice.
Found another problem in my particular situation: the sysvar whose
value I want to put into an ordinary Basic string variable ...
DOES NOT EXIST! As I found by running my Basic app immediately after
a fresh boot. I had forgotten the sysvar is set by something in my
ordinary boot system. Which clearly means the sysvar would not exist
on somebody else's system if I were to distribute the program.
Before trying Basalt, in ordinary Basic I tried v$="phoney" in
SYS"OS_ReadVarVal",v$,END,-1 TO je%,v$
because the spec said that a negative value (-1 here) will test
whether my sysvar (v$) exists and return an error if the answer is no.
(I'm not sure about the stuff after TO; I imitated a previous line.)
00000124: Error from (unknown): System variable 'phoney' not
found
It would be more useful for my present purpose if, instead of that
error message, I could make the function return some arbitrary value
(such as "") and exit. I tried PRINT ERR -- nothing was printed.
Any suggestions?
You want the X form of the SWI to avoid generating an error, and you need to
look at the value in R2 to see if it is zero, as that indicates the variable
does not exist:

DEFFNval(v$)
LOCAL len%
SYS"XOS_ReadVarVal",v$,END,-1,0,3 TO ,,len%
IF len%=0 THEN =""
SYS"OS_ReadVarVal",v$,END,256,0,3 TO ,v$
=v$

Note the value of 3 in R4 which will force the call to convert the variable
value into a string. That avoids problems if the variable is an iteger or a
macro (unless, of course, you want the value in the original form).

The printed PRM on page 1-310 does say ominously that "returned strings are
not terminated and you should use the length returned in R2 when reading
them" so it is possible that the code above might fail. If the strings really
are not terminated then the TO part of the SYS which puts the value into v$
would not work.

(Above code just typed into body of the message without testing, so could be
rubbish.)
--
Matthew Phillips
Durham
Steve Drain
2018-09-06 10:19:06 UTC
Permalink
on 5 Sep 2018 Jim Nagel wrote >> It would be more useful for my present purpose if, instead of that
Post by Jim Nagel
error message, I could make the function return some arbitrary
value (such as "") and exit. I tried PRINT ERR -- nothing was
printed. Any suggestions?
You want the X form of the SWI to avoid generating an error, and you
need to look at the value in R2 to see if it is zero, as that
DEFFNval(v$) LOCAL len% SYS"XOS_ReadVarVal",v$,END,-1,0,3 TO ,,len%
IF len%=0 THEN ="" SYS"OS_ReadVarVal",v$,END,256,0,3 TO ,v$ =v$
Note the value of 3 in R4 which will force the call to convert the
variable value into a string. That avoids problems if the variable is
an iteger or a macro (unless, of course, you want the value in the
original form).
If you are happy to return a null string if the variable does not exist,
I think this can just be:

DEFFNval(v$)
SYS"XOS_ReadVarVal",v$,END,256,,3 TO ,v$
=v$

I would be interested to find the flaws here.

I have left the R4=3 for the reasons you state, but any numerical value
will have to be converted back from the string.
The printed PRM on page 1-310 does say ominously that "returned
strings are not terminated and you should use the length returned in
R2 when reading them" so it is possible that the code above might
fail. If the strings really are not terminated then the TO part of
the SYS which puts the value into v$ would not work.
Yes, that is a puzzle, but I have always found them terminated, so what
do you assume?

It also seems to be that R2 returns 0 when the variable does not exist,
even when you are not explicitly testing for existence.
Matthew Phillips
2018-09-08 09:32:17 UTC
Permalink
Post by Steve Drain
on 5 Sep 2018 Jim Nagel wrote >> It would be more useful for my present purpose if, instead of that
Post by Jim Nagel
error message, I could make the function return some arbitrary
value (such as "") and exit. I tried PRINT ERR -- nothing was
printed. Any suggestions?
You want the X form of the SWI to avoid generating an error, and you
need to look at the value in R2 to see if it is zero, as that
DEFFNval(v$)
LOCAL len%
SYS"XOS_ReadVarVal",v$,END,-1,0,3 TO ,,len%
IF len%=0 THEN =""
SYS"OS_ReadVarVal",v$,END,256,0,3 TO ,v$
=v$
Note the value of 3 in R4 which will force the call to convert the
variable value into a string. That avoids problems if the variable is
an integer or a macro (unless, of course, you want the value in the
original form).
If you are happy to return a null string if the variable does not exist,
DEFFNval(v$)
SYS"XOS_ReadVarVal",v$,END,256,,3 TO ,v$
=v$
I would be interested to find the flaws here.
I think the only doubt in my mind is the state of the memory at END, because
if the variable does not exist, XOS_ReadVarVal does not alter the contents of
the buffer at all. So v$ would get the string that happened to be at END (if
there was one) when the call was entered.

This may or may not be documented, but if it isn't documented I would not
like to rely on it.
Post by Steve Drain
I have left the R4=3 for the reasons you state, but any numerical value
will have to be converted back from the string.
The printed PRM on page 1-310 does say ominously that "returned
strings are not terminated and you should use the length returned in
R2 when reading them" so it is possible that the code above might
fail. If the strings really are not terminated then the TO part of
the SYS which puts the value into v$ would not work.
Yes, that is a puzzle, but I have always found them terminated, so what
do you assume?
Perhaps the SWI documentation is unnecessarily cautious. We can not inspect
the source to see what the OS really does. If it does terminate the strings
with a null byte, and always has, it would be good to update the
documentation so that people know they can rely on the behaviour.
Post by Steve Drain
It also seems to be that R2 returns 0 when the variable does not exist,
even when you are not explicitly testing for existence.
Yes, that much is reasonable, and is implied by the PRM which says that R2 on
exit is the number of bytes read, which would be zero if it can't read any.
--
Matthew Phillips
Durham
Steve Drain
2018-09-08 13:56:24 UTC
Permalink
Post by Matthew Phillips
Post by Steve Drain
I would be interested to find the flaws here.
I think the only doubt in my mind is the state of the memory at END, because
if the variable does not exist, XOS_ReadVarVal does not alter the contents of
the buffer at all. So v$ would get the string that happened to be at END (if
there was one) when the call was entered.
Without following through, I think BASIC is initialising the return
string variable to null), but on the error it does not copy it.
Post by Matthew Phillips
Perhaps the SWI documentation is unnecessarily cautious. We can not inspect
the source to see what the OS really does.
Well, we can, but that might spoil the fun of speculation. ;-)
Alan Adams
2018-09-08 18:39:16 UTC
Permalink
Post by Steve Drain
Post by Matthew Phillips
Post by Steve Drain
I would be interested to find the flaws here.
I think the only doubt in my mind is the state of the memory at END, because
if the variable does not exist, XOS_ReadVarVal does not alter the contents of
the buffer at all. So v$ would get the string that happened to be at END (if
there was one) when the call was entered.
Without following through, I think BASIC is initialising the return
string variable to null), but on the error it does not copy it.
Post by Matthew Phillips
Perhaps the SWI documentation is unnecessarily cautious. We can not inspect
the source to see what the OS really does.
Well, we can, but that might spoil the fun of speculation. ;-)
I see from volume 5A of the PRM (the one containg corrections,
additions) that using OS_ReadVarVal to check for the existence of a
variable Bit 31 of R2 set) corrupts R0 on exit. Just one to watch out
for.
--
Alan Adams, from Northamptonshire
***@adamshome.org.uk
http://www.nckc.org.uk/
Matthew Phillips
2018-09-10 06:27:46 UTC
Permalink
Post by Steve Drain
Post by Matthew Phillips
Post by Steve Drain
I would be interested to find the flaws here.
I think the only doubt in my mind is the state of the memory at END,
because if the variable does not exist, XOS_ReadVarVal does not alter the
contents of the buffer at all. So v$ would get the string that happened
to be at END (if there was one) when the call was entered.
Without following through, I think BASIC is initialising the return
string variable to null), but on the error it does not copy it.
How can that work? If you use XOS_ReadVarVal then there is no error
generated. Does BASIC inspect the V flag and not assign to any of the
registers in the TO list? Or assigns a null string to any string variables
in the TO list? My rather old BASIC manual is silent about this.
Post by Steve Drain
Post by Matthew Phillips
Perhaps the SWI documentation is unnecessarily cautious. We can not
inspect the source to see what the OS really does.
Well, we can, but that might spoil the fun of speculation. ;-)
Sorry, I meant "we can now inspect the source" not "we can not inspect the
source". Mistyping not instead of now is something I have noticed I do from
time to time, and it usually changes the sense of the sentence completely.
Very annoying! I wish I could work out how to reprogramme my neurons to
avoid that trap.
--
Matthew Phillips
Durham
Jim Nagel
2018-09-10 10:37:02 UTC
Permalink
... Sorry, I meant "we can now inspect the source" not "we can not
inspect the source". Mistyping not instead of now is something I have
noticed I do from time to time, and it usually changes the sense of
the sentence completely. Very annoying! I wish I could work out how
to reprogramme my neurons to avoid that trap.
[Warning: editorial tangent]

The word "not" sure does entirely change the sense of a sentence!
Wherefore methinks for clear writing or public speaking, "not" should
absolutely never be shortened to a sloppy mumbled "n't".

(N't that you did it here, Matthew!) (Maybe those neurons could be
trained to substitute "now" with something like "these days".)
--
Jim Nagel www.archivemag.co.uk
"From" address is genuine but will change. Website has current one.
|| See you at the show? www.riscoslondonshow.co.uk Oct 27
News
2018-09-10 13:34:12 UTC
Permalink
Post by Jim Nagel
(N't that you did it here, Matthew!) (Maybe those neurons could be
trained to substitute "now" with something like "these days".)
... and please do not start using 'at this moment in time' 8(
--
Chris Johnson
Alan Adams
2018-09-08 10:20:45 UTC
Permalink
Post by Steve Drain
Post by Jim Nagel
I'm working on a wee Basic program and at one stage I need to compare
mystring$ to a system variable websiteroot$dir.
Must I convert the contents of <websiteroot$dir> to a conventional
Basic string?
Yes.
Post by Jim Nagel
Is there an existing elegant way of doing so?
PRINT FNval("websiteroot$dir")
END
DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$
What is the END there for? It is a BASIC keyword, so there's no error,
but it looks as though it's being used as an address.
Post by Steve Drain
There is no check that it is a string, so a little more effort is needed
for a general routine.
PRINT SYS("websiteroot$dir")
--
Alan Adams, from Northamptonshire
***@adamshome.org.uk
http://www.nckc.org.uk/
Steve Drain
2018-09-08 13:40:20 UTC
Permalink
Post by Alan Adams
Post by Steve Drain
DEFFNval(v$)
SYS"OS_ReadVarVal",v$,END,256 TO ,v$
=v$
What is the END there for? It is a BASIC keyword, so there's no error,
but it looks as though it's being used as an address.
It is.

END as a function returns the free space address (FSA), which is the
next address that BASIC will use to create a heap object. It would be
the address returned by a DIM statement. In the very old days you would
do DIM fsa% -1 to find it.

It is safe to use END in this way as long as you can be confident that
there will be no heap objects (variables etc) created until you have
finished with it. Used in a definition you can make all variables LOCAL
to ensure this (which you do anyway, of course)

This method for getting a buffer for temporary use is very quick, but
used unwisely it could have some interesting consequences. One thing
that might cause a problem could be a very constricted memory. The
STRING$(255,CHR$0) method is completely reliable, as would using a DIM
LOCAL. Using one of BASIC's own buffers, REPBUFF INPBUF, would also have
to be used cautiously.
John Williams (News)
2018-09-04 17:16:57 UTC
Permalink
Post by Jim Nagel
Leads me to think there's something fundamental I need to understand
about the use of sysvars within Basic.
I have saved this useful snippet for further use:

<quote>
Post by Jim Nagel
[...]
DEF PROCsetsysvar(varname$,varval$)
LOCAL vallen%
LOCAL name% , val%
DIM name% LEN(varname$)+1, val% LEN(varname$)+1
$name%=varname$+CHR$(0)
$val%=varval$+CHR$(0)
vallen%=LEN(varval$)
SYS "OS_SetVarVal",name%,val%,vallen%,0,0
ENDPROC
There's no need whatsoever for the explicit DIMming and
0-termination. On SYS calls, BASIC already takes care
of that for you (if there's a string parameter, its
0-terminated value is copied to the BASIC stack, and
discarded after the SYS call).

I.e. simply replace the whole PROC with :

SYS "OS_SetVarVal", varname$, varval$, LEN(varval$), 0, 0
Post by Jim Nagel
DEF FNgetsysvar(varname$)
LOCAL name% ,val% ,vallen%
DIM name% LEN(varname$)+1,val% 200
$name%=varname$+CHR$(0)
SYS "XOS_ReadVarVal",name%,,-1 TO ,,vallen%
IF vallen%<0 THEN
SYS "OS_ReadVarVal",name%,val%,200,0,3 TO ,,vallen%
val%?vallen%=13
ELSE
?val%=13
ENDIF
=$val%
Same thing, also for the return value.

I.e. :

varval$ = ""

SYS "OS_ReadVarVal", varname$, STRING$(255, CHR$0), 255, 0,
3 TO , varval$

(varval$ will be "" if the variable is undefined, the STRING$
reserves a temporary buffer for the return value on the BASIC
stack, which is discarded after the SYS call)


John Kortink

[sig separator removed]

Email : ***@inter.nl.net
Homepage : http://www.inter.nl.net/users/J.Kortink

There's something to be said, for getting out of bed

</quote>

There's also something to be said for saving useful snippets!

Best wishes,

John
--
John Williams, now back in the UK - no attachments to these addresses!
Non-RISC OS posters change user to johnrwilliams or put 'risc' in subject!
Who is John Williams? http://petit.four.free.fr/picindex/author/
Alan Adams
2018-09-04 21:04:24 UTC
Permalink
Post by John Williams (News)
Post by Jim Nagel
Leads me to think there's something fundamental I need to understand
about the use of sysvars within Basic.
<quote>
Post by Jim Nagel
[...]
DEF PROCsetsysvar(varname$,varval$)
LOCAL vallen%
LOCAL name% , val%
DIM name% LEN(varname$)+1, val% LEN(varname$)+1
$name%=varname$+CHR$(0)
$val%=varval$+CHR$(0)
vallen%=LEN(varval$)
SYS "OS_SetVarVal",name%,val%,vallen%,0,0
ENDPROC
There's no need whatsoever for the explicit DIMming and
0-termination. On SYS calls, BASIC already takes care
of that for you (if there's a string parameter, its
0-terminated value is copied to the BASIC stack, and
discarded after the SYS call).
I wrote it that way because from the point of view of the BASIC manual
that behaviour is undefined.
Post by John Williams (News)
SYS "OS_SetVarVal", varname$, varval$, LEN(varval$), 0, 0
Post by Jim Nagel
DEF FNgetsysvar(varname$)
LOCAL name% ,val% ,vallen%
DIM name% LEN(varname$)+1,val% 200
$name%=varname$+CHR$(0)
SYS "XOS_ReadVarVal",name%,,-1 TO ,,vallen%
IF vallen%<0 THEN
SYS "OS_ReadVarVal",name%,val%,200,0,3 TO ,,vallen%
val%?vallen%=13
ELSE
?val%=13
ENDIF
=$val%
Same thing, also for the return value.
varval$ = ""
SYS "OS_ReadVarVal", varname$, STRING$(255, CHR$0), 255, 0,
3 TO , varval$
(varval$ will be "" if the variable is undefined, the STRING$
reserves a temporary buffer for the return value on the BASIC
stack, which is discarded after the SYS call)
John Kortink
[sig separator removed]
Homepage : http://www.inter.nl.net/users/J.Kortink
There's something to be said, for getting out of bed
</quote>
There's also something to be said for saving useful snippets!
Best wishes,
John
--
Alan Adams, from Northamptonshire
***@adamshome.org.uk
http://www.nckc.org.uk/
Matthew Phillips
2018-09-05 07:03:20 UTC
Permalink
Post by Alan Adams
Post by John Williams (News)
Post by Jim Nagel
Leads me to think there's something fundamental I need to understand
about the use of sysvars within Basic.
<quote>
Post by Jim Nagel
[...]
DEF PROCsetsysvar(varname$,varval$)
LOCAL vallen%
LOCAL name% , val%
DIM name% LEN(varname$)+1, val% LEN(varname$)+1
$name%=varname$+CHR$(0)
$val%=varval$+CHR$(0)
vallen%=LEN(varval$)
SYS "OS_SetVarVal",name%,val%,vallen%,0,0
ENDPROC
There's no need whatsoever for the explicit DIMming and
0-termination. On SYS calls, BASIC already takes care
of that for you (if there's a string parameter, its
0-terminated value is copied to the BASIC stack, and
discarded after the SYS call).
I wrote it that way because from the point of view of the BASIC manual
that behaviour is undefined.
Strange. In the BBC BASIC Guide published in 1988 for the Archimedes 400
series under the description of the SYS command it says "if the expression
evaluates to a string, the string is placed on BASIC's stack, beginning at a
word boundary and terminated with a null character. A pointer to it is put in
the register."

There were other problems with the routine which John Kortink did not point
out. The most serious was that val% is being dimensioned to the length of
varname$ not varval$. Another is that, because you are adding a null
character after the string, you actually need LEN(varval$)+2 because placing
varval$+CHR$(0) in the buffer will actually add a terminating return
character after the CHR$(0). Finally, every time the routine is used it will
leak memory, because the memory allocated by DIM is not freed by BASIC
afterwards. It is only the references to it in name% and val% that are
discarded. This is not easily fixed across all versions of BASIC except by
using a global buffer, but newer versions of BASIC have DIM LOCAL:

DIM name% LOCAL LEN(varname$)+2

I'm not sure which branches of RISC OS have this and when it was introduced.

Sorry to go over old code -- we've all moved on since then and learned more
-- but I thought I'd better mention it in case you still have this routine in
use on the "if it ain't broke don't fix it" principle.
--
Matthew Phillips
Durham
Martin Wuerthner
2018-09-05 12:39:49 UTC
Permalink
<quote> On Tue, 06 Oct 2009 17:17:52 +0100, Alan Adams
Post by Jim Nagel
[...]
DIM name% LEN(varname$)+1
[...]
$name%=varname$+CHR$(0)
[...] because you are adding a
null character after the string, you actually need LEN(varval$)+2 because
placing varval$+CHR$(0) in the buffer will actually add a terminating
return character after the CHR$(0)
While you made many valid points in your posting, this one is actually
incorrect. DIM name% X reserves X+1 bytes, so LEN(varname$)+1 is just the
right size - it reserves LEN(varname$)+2 bytes, enough for the two
terminators.
--
Martin Wuerthner MW Software http://www.mw-software.com/

------- RISC OS Software for Design, Printing and Publishing --------
Matthew Phillips
2018-09-05 18:45:42 UTC
Permalink
Post by Martin Wuerthner
<quote> On Tue, 06 Oct 2009 17:17:52 +0100, Alan Adams
Post by Jim Nagel
[...]
DIM name% LEN(varname$)+1
[...]
$name%=varname$+CHR$(0)
[...] because you are adding a
null character after the string, you actually need LEN(varval$)+2 because
placing varval$+CHR$(0) in the buffer will actually add a terminating
return character after the CHR$(0)
While you made many valid points in your posting, this one is actually
incorrect. DIM name% X reserves X+1 bytes, so LEN(varname$)+1 is just the
right size - it reserves LEN(varname$)+2 bytes, enough for the two
terminators.
Well, I'm glad I responded because I've learned something too. That is quite
surprising, but I suppose that behaviour is consistent with dimensioning
arrays, where

DIM a%(10)

creates an array where the last indexed entry is at 10, but with the first
being a%(0) the array contains 11 items.

Thanks, Martin, and apologies to Adam!
--
Matthew Phillips
Durham
Steve Drain
2018-09-06 10:24:04 UTC
Permalink
Post by Matthew Phillips
Post by Martin Wuerthner
While you made many valid points in your posting, this one is actually
incorrect. DIM name% X reserves X+1 bytes, so LEN(varname$)+1 is just the
right size - it reserves LEN(varname$)+2 bytes, enough for the two
terminators.
Well, I'm glad I responded because I've learned something too. That is quite
surprising, but I suppose that behaviour is consistent with dimensioning
arrays, where
DIM a%(10)
creates an array where the last indexed entry is at 10, but with the first
being a%(0) the array contains 11 items.
It is hardly important with the amount of memory we have, but "in the
old days" a DIM had to be carefully considered. Noting that the reserved
space is word-aligned, adding 1 where not necessary could waste 4 bytes. ;-)
John Williams (News)
2018-09-05 19:56:01 UTC
Permalink
Well, as it turns out, I'm glad I mentioned it!

John
--
John Williams, now back in the UK - no attachments to these addresses!
Non-RISC OS posters change user to johnrwilliams or put 'risc' in subject!
Who is John Williams? http://petit.four.free.fr/picindex/author/
svrsig
2018-09-06 03:13:09 UTC
Permalink
Post by John Williams (News)
Well, as it turns out, I'm glad I mentioned it!
John
--
John Williams, now back in the UK - no attachments to these addresses!
Non-RISC OS posters change user to johnrwilliams or put 'risc' in subject!
Who is John Williams? http://petit.four.free.fr/picindex/author/
I use the following code which avoids errors but uses numbers not strings:
70 : SYS "XOS_ReadVarVal","SatNav$AllowPlay",,-1 TO ,,allowplay%
80 : IF allowplay% THEN SYS "XOS_ReadVarVal","SatNav$AllowPlay",qbuf%,1
90 TO ,,,,r4%:IF ?qbuf%=ASC("1") THEN allowplay%=TRUE ELSE allowpl
ay%=FALSE
Matthew Phillips
2018-09-06 06:21:54 UTC
Permalink
Post by svrsig
70 : SYS "XOS_ReadVarVal","SatNav$AllowPlay",,-1 TO ,,allowplay%
80 : IF allowplay% THEN SYS "XOS_ReadVarVal","SatNav$AllowPlay",qbuf%,1
90 TO ,,,,r4%:IF ?qbuf%=ASC("1") THEN allowplay%=TRUE ELSE allowpl
ay%=FALSE
Safer to pass 3 in R4 on entry in case any of your users have set up the
variable as a macro. With R4 set to zero, you'll be reading the macro
definition, not the value it would currently resolve to.
--
Matthew Phillips
Durham
A. N. Other
2018-09-04 17:11:10 UTC
Permalink
Post by Jim Nagel
I'm working on a wee Basic program and at one stage I need to compare
mystring$ to a system variable websiteroot$dir.
[snipped]
Post by Jim Nagel
headfile$ = "<websiteroot$dir>.fefi.fofum.head"
mytail% = OPENIN "<websiteroot$dir>.fefi.fofum.tail"
PRINT websiteroot$dir
Same error whether or not I use anglebrackets <websiteroot$dir>.
Leads me to think there's something fundamental I need to understand
about the use of sysvars within Basic. Web search brought up various
articles and PRM references but nothing seemed to the point. Can
anyone enlighten me, please?
[snipped]
Post by Jim Nagel
Must I convert the contents of <websiteroot$dir> to a conventional
Basic string? Is there an existing elegant way of doing so?
Am I overlooking something obvious, or can you not simply do:

PRINT "<websiteroot$dir>"

or

root$ = "<websiteroot$dir>"
Post by Jim Nagel
*show websiteroot$dir { > tempfile }
(Don't know where I ever found that "{ > xyz }" business. Found no
mention in the new User Guide or online, probably not easy to index.
I vaguely remembered it from some dark mental crevice and played with
spaces etc until, surprise, it worked. What's it called?)
Redirection, and I think it *is* in the RO5 User Guide.
Jim Nagel
2018-09-04 17:42:28 UTC
Permalink
Post by A. N. Other
Post by Jim Nagel
Must I convert the contents of <websiteroot$dir> to a conventional
Basic string? Is there an existing elegant way of doing so?
PRINT "<websiteroot$dir>"
No. The result of that is defiantly literal:
<websiteroot$dir>
Post by A. N. Other
Post by Jim Nagel
*show websiteroot$dir { > tempfile }
(Don't know where I ever found that "{ > xyz }" business. Found no
mention in the new User Guide or online, probably not easy to index.
I vaguely remembered it from some dark mental crevice and played with
spaces etc until, surprise, it worked. What's it called?)
Redirection, and I think it *is* in the RO5 User Guide.
You're right; there it is. But only NOW do I know that the term I
needed to look up in the index is "redirection".

Shows how helpful people in the Acorn newsgroups can be!
--
Jim Nagel www.archivemag.co.uk
|| See you at the show? www.riscoslondonshow.co.uk Oct 27
Matthew Phillips
2018-09-05 07:08:12 UTC
Permalink
Post by Jim Nagel
Post by A. N. Other
Post by Jim Nagel
Must I convert the contents of <websiteroot$dir> to a conventional
Basic string? Is there an existing elegant way of doing so?
PRINT "<websiteroot$dir>"
<websiteroot$dir>
Yes, that's expected. After all, how on earth could you get the <> characters
into a string if the above syntax caused system variables to be interpolated.
It would be very annoying.

The explanation, Jim as to why your original example worked...

headfile$ = "<websiteroot$dir>.fefi.fofum.head"
mytail% = OPENIN "<websiteroot$dir>.fefi.fofum.tail"

...is that OPENIN passes the whole string exactly as it is to FileSwitch, and
FileSwitch or the filing systems underneath interpret the system variable.
Similarly the BASIC OSCLI command just sends the whole string to the command
line interpreter, and that interprets the command line.

BASIC has absolutely no knowledge of system variables.
--
Matthew Phillips
Durham
j***@mdfs.net
2018-09-07 00:12:33 UTC
Permalink
Post by Jim Nagel
PRINT websiteroot$dir
'cos that's not a BASIC variable.
Post by Jim Nagel
Same error whether or not I use anglebrackets <websiteroot$dir>.
'cos that's not a BASIC variable.

Do you *need* to know what <websiteroot$dir> is? Filing
system path expansion is done by, well, the filing system.
channel%=OPENIN("<websiteroot$dir>.foo.bar.whatever")
Loading...