Discussion:
Filetype list
(too old to reply)
Harriet Bazley
2018-04-29 22:38:44 UTC
Permalink
I've been trying to find out why Textseek's code to generate a list of all
available filetypes is crashing on the ARMiniX.

What I've currently got is an attempt to measure the number of filetypes

DEF FNcountfiletypes
LOCAL ptr%,n%,err%
REPEAT
n%+=1
SYS"XOS_ReadVarVal","File$Type_*",wimp%,255,ptr% TO ,,,ptr%;err%
UNTIL err% AND 1
=n%-1

in order to dimension the various menu blocks correctly, followed by

REPEAT
SYS"XOS_ReadVarVal","File$Type_*",block%,255,ptr% TO ,,bytes%,ptr%;err%
IF bytes% THEN
block%?bytes%=13
$textptr%=FNs(block%)
$(textptr%+10)=FNs(ptr%+10)
textptr%+=14
ENDIF
UNTIL bytes%=0

Apparently on the new machine it's possible for OSReadVarVal to return R2=0
without having reached the end of the wildcarded list, and without
generating an error. So even if I change the terminating condition to
check for an error from the XOS call, I still have the problem that
FNcountfiletypes is returning too high a value on account of the random null
values being skipped over in the middle of the loop, and that I thus have
rubbish menu entries at the end of the list filled with undefined data.

Has this SWI changed in later versions of the OS? (This code was written
for RISC OS 3.1), and quite probably copied out of someone else's PD
application in the first place....
--
Harriet Bazley == Loyaulte me lie ==

We prefer to speak evil of ourselves than not speak of ourselves at all.
Martin
2018-04-30 09:54:42 UTC
Permalink
Post by Harriet Bazley
I've been trying to find out why Textseek's code to generate a list of
all available filetypes is crashing on the ARMiniX.
That immediately makes me wonder if it is something peculiar to the
ARMiniX, not later versions of the OS.

You do not say how it is crashing, or in which line of code, or what OS
version is being used.
Post by Harriet Bazley
What I've currently got is an attempt to measure the number of filetypes
DEF FNcountfiletypes
LOCAL ptr%,n%,err%
REPEAT
n%+=1
SYS"XOS_ReadVarVal","File$Type_*",wimp%,255,ptr% TO ,,,ptr%;err%
UNTIL err% AND 1
=n%-1
This does read the variable ... just to check if one exists r2 should be
negative on entry. I am not sure if checking for an error is the correct
termination.

Nether the PRM nor StrongHelp manual is clear to me how to terminate a
wildcarded call. But it seems that r3 is zero when there are no more,
which seems reasonable.

I suspect r2 can return zero if the variable value is a null string?

Perhaps the ARMiniX for some reason has a filetype with a null string?
Post by Harriet Bazley
in order to dimension the various menu blocks correctly, followed by
REPEAT
SYS"XOS_ReadVarVal","File$Type_*",block%,255,ptr% TO ,,bytes%,ptr%;err%
IF bytes% THEN
block%?bytes%=13
$textptr%=FNs(block%)
$(textptr%+10)=FNs(ptr%+10)
textptr%+=14
ENDIF
UNTIL bytes%=0
This will terminate on the first null value.
Post by Harriet Bazley
Apparently on the new machine it's possible for OSReadVarVal to return
R2=0 without having reached the end of the wildcarded list, and without
generating an error. So even if I change the terminating condition to
check for an error from the XOS call, I still have the problem that
FNcountfiletypes is returning too high a value on account of the random
null values being skipped over in the middle of the loop, and that I
thus have rubbish menu entries at the end of the list filled with
undefined data.
I suggest that you need to have the REPEAT...UNTIL conditions the same in
both the count and to get the values - then at least they must be
consistent!
Post by Harriet Bazley
Has this SWI changed in later versions of the OS? (This code was
written for RISC OS 3.1), and quite probably copied out of someone
else's PD application in the first place....
I am using RISC OS 5.24 here ... which is probably later than the
ARMiniX, and I have just run TextSeek v1.47 and the full list works fine
... though having added a null value for File$Type_XXX I have seen some
blank or duplicated menu entries.

Martin
--
Martin Avison
Note that unfortunately this email address will become invalid
without notice if (when) any spam is received.
Harriet Bazley
2018-04-30 22:43:20 UTC
Permalink
On 30 Apr 2018 as I do recall,
Post by Martin
Post by Harriet Bazley
I've been trying to find out why Textseek's code to generate a list of
all available filetypes is crashing on the ARMiniX.
That immediately makes me wonder if it is something peculiar to the
ARMiniX, not later versions of the OS.
You do not say how it is crashing, or in which line of code, or what OS
version is being used.
It was crashing in PROCmakemenu at a later stage, when attempting to read
data from a pointer that was pointing into a random memory location and
retrieving a string that was too long for BASIC.
Sometimes (when the random locations are less disastrous) it wasn't
crashing, but was generating a menu with gibberish entries.
Post by Martin
Post by Harriet Bazley
What I've currently got is an attempt to measure the number of filetypes
DEF FNcountfiletypes
LOCAL ptr%,n%,err%
REPEAT
n%+=1
SYS"XOS_ReadVarVal","File$Type_*",wimp%,255,ptr% TO ,,,ptr%;err%
UNTIL err% AND 1
=n%-1
This does read the variable ... just to check if one exists r2 should be
negative on entry. I am not sure if checking for an error is the correct
termination.
Nether the PRM nor StrongHelp manual is clear to me how to terminate a
wildcarded call. But it seems that r3 is zero when there are no more,
which seems reasonable.
I suspect r2 can return zero if the variable value is a null string?
i.e. the system variable *exists*, therefore the call returns, but has no
value?
Post by Martin
Perhaps the ARMiniX for some reason has a filetype with a null string?
This is what I'm beginning to suspect -- that it's not an OS-specific thing,
but peculiar to that individual machine, and that something I booted is
setting null variables.
(In fact I believe that some of the UNIX ports instruct you to set up null
variables to configure their behaviour, now that I mention it....)
--
Harriet Bazley == Loyaulte me lie ==

Hypocrisy is underrated.
t***@cestriant.plus.com
2018-04-30 14:12:01 UTC
Permalink
Post by Harriet Bazley
I've been trying to find out why Textseek's code to generate a list of all
available filetypes is crashing on the ARMiniX.
Apologies if I'm misunderstanding your problem, but I've loaded
TextSeek v 1.47Beta on the ArminiX (OS 5.22) and the 'list all
filetypes' menu appears without problem and doesn't cause a crash.
--
Regards,
Terry
Matthew Phillips
2018-05-01 07:31:09 UTC
Permalink
Post by Harriet Bazley
I've been trying to find out why Textseek's code to generate a list of all
available filetypes is crashing on the ARMiniX.
What I've currently got is an attempt to measure the number of filetypes
DEF FNcountfiletypes
LOCAL ptr%,n%,err%
REPEAT
n%+=1
SYS"XOS_ReadVarVal","File$Type_*",wimp%,255,ptr% TO ,,,ptr%;err%
UNTIL err% AND 1
=n%-1
in order to dimension the various menu blocks correctly, followed by
REPEAT
SYS"XOS_ReadVarVal","File$Type_*",block%,255,ptr% TO ,,bytes%,ptr%;err%
IF bytes% THEN
block%?bytes%=13
$textptr%=FNs(block%)
$(textptr%+10)=FNs(ptr%+10)
textptr%+=14
ENDIF
UNTIL bytes%=0
Apparently on the new machine it's possible for OSReadVarVal to return R2=0
without having reached the end of the wildcarded list, and without
generating an error. So even if I change the terminating condition to
check for an error from the XOS call, I still have the problem that
FNcountfiletypes is returning too high a value on account of the random null
values being skipped over in the middle of the loop, and that I thus have
rubbish menu entries at the end of the list filled with undefined data.
I find the documentation of OS_ReadVarVal on page 1-309 of the PRM to be
particularly bad. It is not at all clear how you are meant to tell you have
read all the variables in the wildcarded case.

Page 1-332 provides an example piece of code which terminates when the SWI
returns an error, which is what you are doing in your first loop.

The trouble is that the SWI documentation exhorts you to find the length of
the variable value first by setting bit 31 of R2 on entry, and then says that
"you may get an error on exit, which you should ignore". I don't know how
you are meant to tell the difference between the error that terminates the
loop and a random error that may occur when testing the length.

Overall it's not a good API, and the fact it is a bit of a bodge is clear
when you realise that in RISC OS 2 it was not even possible to determine the
buffer length required.

I did a simple test:

*set ggg ""
*show ggg
ggg :

Then in BASIC:

DIM a% 256
SYS"OS_ReadVarVal","ggg",a%,256,0,0 TO ,,len%
P.len%

This printed zero. So it's certainly possible to have zero bytes returned
for the length in R2.

If you are trying to create a menu of all filetypes, then you could consider
using the variable *name* instead of its value when R2 is returned as zero.
Or extracting the hexadecomal part of the name and adding that to the menu.
A pointer to the variable name is returned in R3. The PRM does not state
whether the name in R3 is null-terminated or just control-character
terminated. Either way you're probably not meant to modify the memory
pointed to by R3.

If you don't wnat these duff entries to appear, then you may just have to
modify the length of the menu in your second loop.
--
Matthew Phillips
Durham
Martin
2018-05-01 09:47:21 UTC
Permalink
Post by Matthew Phillips
Post by Harriet Bazley
I've been trying to find out why Textseek's code to generate a list
of all available filetypes is crashing on the ARMiniX.
I find the documentation of OS_ReadVarVal on page 1-309 of the PRM to
be particularly bad. It is not at all clear how you are meant to tell
you have read all the variables in the wildcarded case.
I agree totally - it is very confusing.
Post by Matthew Phillips
The trouble is that the SWI documentation exhorts you to find the
length of the variable value first by setting bit 31 of R2 on entry,
and then says that "you may get an error on exit, which you should
ignore". I don't know how you are meant to tell the difference between
the error that terminates the loop and a random error that may occur
when testing the length.
I have had a quick look at the code for the *Show command, and it seems
to use the error numbers to differentiate:
&124 = System variable ??? not found
&1E4 = Buffer overflow

At the end of a wildcarded list you receive error &124, and r3 is set to
zero, so either should be usable to end enumeration.

If the buffer is too small (and that includes when the r2 is negative on
entry) you receive error &1E4.
Post by Matthew Phillips
So it's certainly possible to have zero bytes returned for the length
in R2.
That is returned (without error) if the value is null.

Null values should either be included in the count or the menu, or
excluded from both. As long as they are the same!
Post by Matthew Phillips
A pointer to the variable name is returned in R3. The PRM does not
state whether the name in R3 is null-terminated or just
control-character terminated.
It seems to be null-terminated.

Martin
--
Martin Avison
Note that unfortunately this email address will become invalid
without notice if (when) any spam is received.
Harriet Bazley
2018-05-07 22:21:59 UTC
Permalink
On 1 May 2018 as I do recall,
Post by Matthew Phillips
Post by Harriet Bazley
I've been trying to find out why Textseek's code to generate a list of all
available filetypes is crashing on the ARMiniX.
[snip]
Post by Matthew Phillips
*set ggg ""
*show ggg
DIM a% 256
SYS"OS_ReadVarVal","ggg",a%,256,0,0 TO ,,len%
P.len%
This printed zero. So it's certainly possible to have zero bytes returned
for the length in R2.
Yes, this definitely seems to be what was causing the problem - an
application setting up filetypes without giving them names.
Post by Matthew Phillips
If you are trying to create a menu of all filetypes, then you could
consider using the variable *name* instead of its value when R2 is
returned as zero. Or extracting the hexadecomal part of the name and
adding that to the menu.
I've gone for that version. Also, after a lot of fiddling around with
multiple nested conditions, WHILE versus REPEAT etc, it dawned on me that
having calculated the number of entries on the menu (in order to reserve
memory accordingly!) I could simply use the pre-calculated value in a
FOR...NEXT loop, and use the non-X form of the SWI instead of trying to trap
errors in order to end the loop:

FOR n% = 1 TO max%
SYS"OS_ReadVarVal","File$Type_*",block%,255,ptr% TO ,,bytes%,ptr%
IF bytes% THEN
block%?bytes%=13
$textptr%=FNs(block%)
ELSE
$(textptr%)=FNs(ptr%+10):REM use hex filetype for nameless variables
ENDIF
$(textptr%+10)=FNs(ptr%+10)
textptr%+=14
NEXT n%



It seems to work correctly in that the last entry on the menu is 'Zip',
which comes at the end of the alphabet - so nothing is being dropped off -
and the code is no longer causing buffer overruns by trying to access
non-existent strings in memory....
--
Harriet Bazley == Loyaulte me lie ==

Old Programmers never die. They just terminate and stay resident
Harriet Bazley
2018-05-07 22:37:55 UTC
Permalink
On 7 May 2018 as I do recall,

Harriet Bazley wrote:

[snip]
Post by Harriet Bazley
It seems to work correctly in that the last entry on the menu is 'Zip',
which comes at the end of the alphabet - so nothing is being dropped off -
and the code is no longer causing buffer overruns by trying to access
non-existent strings in memory....
And after all that... I've just gone to update my original source files and
discovered that I'd ALREADY patched this bug back in September 2015 and by
the exact same process, plus an additional issue. I just hadn't ever
uploaded that update to the website!
--
Harriet Bazley == Loyaulte me lie ==

The purpose of rules is to make you think before you break them.
Loading...