Running on RO 5.14.
The following bit of BASIC finds the current time, converts it to
text. So far so good.
Then I convert the text to a binary time, and back to text. The result
is ALWAYS the day before.
ON ERROR PRINT REPORT$;" at line ";ERL:END
DIM buf% 512, time% 5, format% 60, date% 60, temp% 60, ordinals% 32
PROCgettime(time%)
?date%=0
today$=FNtimebin2str(time%)
PRINT today$
PROCtimestr2bin(today$,time%)
today$=FNtimebin2str(time%)
PRINT today$
END
DEF PROCgettime(buf%)
?buf%=3
SYS "OS_Word",14,buf%
ENDPROC
DEF PROCtimestr2bin(time$,buf%)
$temp%=time$+CHR$(0)
REM time$ must be in format %W3, %DY-%M3-%CE%YR
SYS "Territory_ConvertTimeStringToOrdinals",-1,2,temp%,ordinals%
SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
ENDPROC
DEF FNtimebin2str(buf%)
LOCAL time$, date$
?date%=0
$format%="%W3, %DY-%M3-%CE%YR"+CHR$(13)+CHR$(0)
SYS "Territory_ConvertDateAndTime",-1,buf%,date%,40,format%
time$=$date%
=time$
--
Alan Adams, from Northamptonshire
al...@adamshome.org.uk
http://www.nckc.org.uk/
> Is it me, or is this doing something odd?
>
> Running on RO 5.14.
>
> The following bit of BASIC finds the current time, converts it to
> text. So far so good.
>
> Then I convert the text to a binary time, and back to text. The result
> is ALWAYS the day before.
>
> ON ERROR PRINT REPORT$;" at line ";ERL:END
>
> DIM buf% 512, time% 5, format% 60, date% 60, temp% 60, ordinals% 32
I have no idea if this is relevant, but you've DIMmed buf% and time% etc
here, so they are global values...
>
> PROCgettime(time%)
and here you're needlessly passing the value of time% as a parm
> DEF PROCgettime(buf%)
and now you've used a formal parameter buf% which is presumably not the same
as the DIMmed one above. Or is it? - I'm confused.
--
Jeremy C B Nicoll - my opinions are my own.
Email sent to my from-address will be deleted. Instead, please reply
to newsre...@wingsandbeaks.org.uk replacing "nnn" by "284".
Sorry, but it is you!
[Snip]
Your code
> SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
preserves R2, but it does *not* preserve the storage *at* R2!
When I ran it just now,
today$="Sat, 24-Oct-2009"
Memory Dump From ~(buf%)=&9444 Length (5)=5
00009444 �C5 41 77 AF�50
But after the SWI conversion ...
Memory Dump From ~(buf%)=&9444 Length (5)=5
00009444 �AB B3 F0 AE�50
The suprising thing it is only 1 day out!
Martin
--
Martin Avison
Note that unfortunately this email address will become invalid
without notice if (when) any spam is received.
> Alan Adams <al...@adamshome.org.uk> wrote:
>> Is it me, or is this doing something odd?
>>
>> Running on RO 5.14.
>>
>> The following bit of BASIC finds the current time, converts it to
>> text. So far so good.
>>
>> Then I convert the text to a binary time, and back to text. The result
>> is ALWAYS the day before.
>>
>> ON ERROR PRINT REPORT$;" at line ";ERL:END
>>
>> DIM buf% 512, time% 5, format% 60, date% 60, temp% 60, ordinals% 32
> I have no idea if this is relevant, but you've DIMmed buf% and time% etc
> here, so they are global values...
>>
>> PROCgettime(time%)
> and here you're needlessly passing the value of time% as a parm
It's only needless in the example. In the program it was extracted
from, there are several different buffers holding different times, so
the passed parameter identifies which one is to be used.
>> DEF PROCgettime(buf%)
> and now you've used a formal parameter buf% which is presumably not the same
> as the DIMmed one above. Or is it? - I'm confused.
Not necessarily the same.
As standard BASIC doesn't have LOCAL DIM, there are some areas where
the necessity is to DIM buffers in the main program, even when they're
only used in subroutines.
> SYS "Territory_ConvertTimeStringToOrdinals",-1,2,temp%,ordinals%
Any fields not specified by the format string will be set to -1 in the
ordinals% buffer. As we're using the format string "%W3, %DY-%M3-%CE%YR"
here, all the time fields will be set to -1.
> SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
This SWI however doesn't treat the -1s as a special values and tries to
convert them to a valid time, this causes the date to be mangled. To get
the correct date you'll need to set the time fields in buffer ordinals%
to 0 before calling this SWI.
--
Fred Graute
http://www.stronged.iconbar.com/
[Snip]
> Your code
> > SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
> preserves R2, but it does *not* preserve the storage *at* R2!
What a b****y stupid reply of mine! Of *course* it does not 'preserve the
storage at R2', as it is supposed to chenge it!!
REPEAT
I must not post when I want to go to bed
UNTIL asleep
> The suprising thing it is only 1 day out!
Fred is absolutely correct in his reply: if the ordinals hour, minute,
second and centisecond values are all -1, the string time seems to be set
to 22:58:58 and the day is reduced by one.
> On 24 Oct, in article <c5a86faf50...@laptop.adamshome.org.uk>,
> Alan Adams <al...@adamshome.org.uk> wrote:
>> Is it me, or is this doing something odd?
> Sorry, but it is you!
> [Snip]
> Your code
>> SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
> preserves R2, but it does *not* preserve the storage *at* R2!
> When I ran it just now,
> today$="Sat, 24-Oct-2009"
> Memory Dump From ~(buf%)=&9444 Length (5)=5
> 00009444 �C5 41 77 AF�50
> But after the SWI conversion ...
> Memory Dump From ~(buf%)=&9444 Length (5)=5
> 00009444 �AB B3 F0 AE�50
> The suprising thing it is only 1 day out!
> Martin
Not exactly. The procedure has time$ as input, and puts its output in
buf%.
Step one is Territory_ConvertTimeStringToOrdinals, which produces 7
values ranging from year to centiseconds. As I only pass in a date,
using reason code 2 which expects that, all the time values are set to
-1.
Step 2 is Territory_ConvertOrdinalsToTime, which uses the ordinals
created above, and puts the result in buf%, which as you say, changes
the contents of buf%.
The significance of the small change you observed above is that before
the call buf% held the current date and time. Afterwards it holds
yesterday's date.
If I change the 4 ordinals corresponding to times from -1 to 0 between
the calls, I get the right date back.
The paper PRM I am using doesn't say what is put into the time values
when only a date is passed, using reason code 2. It doesn't say what
is meant by -1 in those values. Fudging the result, by setting them to
0, seems to work, but I don't like it.
I've changed the format string in FMtimebin2str to return the time as
well as the date.
Now, without changing -1 to 0, I get
today$="Sun, 25-Oct-2009.12:21:04"
today$="Sat, 24-Oct-2009.22:58:58"
Changing -1 to 0 produces
today$="Sun, 25-Oct-2009.12:22:15"
today$="Sun, 25-Oct-2009.00:00:00"
So the question now is why is the time being changed back by about 13
hours?
======== current version of program follows ==============
ON ERROR PRINT REPORT$;" at line ";ERL:END
DIM buf% 512, time% 5, format% 60, date% 60, temp% 60, ordinals% 32
PROCgettime(time%)
?date%=0
today$=FNtimebin2str(time%)
*report today$
PROCtimestr2bin(today$,time%)
today$=FNtimebin2str(time%)
*report today$
END
DEF PROCgettime(buf%)
?buf%=3
SYS "OS_Word",14,buf%
ENDPROC
DEF PROCtimestr2bin(time$,buf%)
$temp%=time$+CHR$(0)
REM time$ must be in format %W3, %DY-%M3-%CE%YR
SYS "Territory_ConvertTimeStringToOrdinals",-1,2,temp%,ordinals%
REM remove next line to test without resetting time element.
ordinals%!0=0:ordinals%!4=0:ordinals%!8=0:ordinals%!12=0
SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
ENDPROC
DEF FNtimebin2str(buf%)
LOCAL time$, date$
?date%=0
$format%="%W3, %DY-%M3-%CE%YR.%24:%MI:%SE"+CHR$(13)+CHR$(0)
> On 24 Oct, in article <50af7795...@avisoft.f9.co.uk>,
> Martin <New...@avisoft.f9.co.uk> wrote:
>> On 24 Oct, in article <c5a86faf50...@laptop.adamshome.org.uk>,
>> Alan Adams <al...@adamshome.org.uk> wrote:
> [Snip]
>> Your code
>>> SYS "Territory_ConvertOrdinalsToTime",-1,buf%,ordinals%
>> preserves R2, but it does *not* preserve the storage *at* R2!
> What a b****y stupid reply of mine! Of *course* it does not 'preserve the
> storage at R2', as it is supposed to chenge it!!
> REPEAT
> I must not post when I want to go to bed
> UNTIL asleep
>> The suprising thing it is only 1 day out!
> Fred is absolutely correct in his reply: if the ordinals hour, minute,
> second and centisecond values are all -1, the string time seems to be set
> to 22:58:58 and the day is reduced by one.
I suspect it is one hour, one minute, one second and one centisecond
before midnight on the day in question. i.e. it treats the -1 values
as valid instead of special.
> Martin
Of course the reason for this slightly convoluted approach is that I
couldn't find a way of converting from a string to a binary time in
one setep. Have I missed something?
> alan wrote:
>> As standard BASIC doesn't have LOCAL DIM, there are some areas where
>> the necessity is to DIM buffers in the main program, even when they're
>> only used in subroutines.
> If you're absolutely certain that nothing is going to be added to
> the heap in the duration of the subroutine and you're absolutely
> certain about how much heap space there is:
> LOCAL temp%:DIM temp% -1
> !temp%=a_value
> $temp%="a string"
> etc.
Unfortunately I'd have to say NO to both of these. The code example
came from a library used by a number of programs, most in active
development. It's not impossible that other routines would be called
from the one in question before it ended.
> As standard BASIC doesn't have LOCAL DIM, there are some areas where
> the necessity is to DIM buffers in the main program, even when
> they're only used in subroutines.
The trick, of course, is to use a memory management library. (Or a
trivial binding to OS_Heap.)
B.
First, a small point. There has been no need to use the DIM temp% -1
trick since BASIC V. END as a function returns the value of FSA, the
free space address, which is what you want, so temp%=END will do.
> Unfortunately I'd have to say NO to both of these. The code example
> came from a library used by a number of programs, most in active
> development. It's not impossible that other routines would be called
> from the one in question before it ended.
Of course, I would recommend Basalt to you, but if that is not feasible
you can fudge a DIM LOCAL with a local array, but it is a bit messy.
REM call once to initialise an array and keep its pointer
PROC_DIM_LOCAL
PROCtest
...
END
DEFPROC_DIM_LOCAL:LOCAL L%():L%=END-4:ENDPROC
REM the number 4 depends on single letter array name and resident integer
DEFFN_DIM_LOCAL(bytes%):DIM L%(bytes%/4-4):=!L%
REM roughly equivalent to DIM block% LOCAL bytes%-1 - minimum 16
DEFPROCtest
LOCAL block%,L%():block%=FN_DIM_LOCAL(32)
...
ENDPROC
You can use the initialised array name locally in as many procedures as
you need and to any depth - I think!
--
; ,', * Basalt * - gives RO 3.10+ versions of BASIC V new and alternative
;,' keywords, dynamic memory for arrays and blocks, new variable types.
;', Legal, fast and simple to use. Freeware - version 0.98� - 19 Aug 03
,; ',, Steve Drain, Kappa : http://www.kappa.me.uk/basalt.htm
It's such a pity ARM BASIC doesn't provide a legitimate way to find
the address of an array. It was trivially easy to add that facility
to BBC BASIC for Windows (I use the unary ^ operator). In fact your
procedure above *does* also work in BB4W, but other than for reasons
of compatibility there's no reason to use it:
PROC_DIM_LOCAL
PRINT L%
PRINT ^L%()
268703608
268703608
>
Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
I was playing around with the development version of Basalt recently
to add an "address-of" function. I have found that the ^ operator is
too difficult to use in the way Basalt works, but PTR is handy; so:
address%=PTR(L%())
This can work with all the objects that BB4W offers, including PROC and
FN, and I wrote a form of passing such a pointer as a parameter, too. I
still do not see it is any more useful than passing the name of a FN,
though, especially as I have included LET name$=FNname to assign the
name to a string dynamically to make it immune to crunching. ;-)
Anyway, I first implemented PTR to evaluate the actual address
of the data in an object, eg: pass the address of a string. Then I
looked at BB4W and saw that you do it more simply and pass just the
l-value. So, for example, to get the address of a string you need !PTR
but a float is just PTR. This feels inconsistent to me, so I would like
to solicit opinions from anyone here as to the better version; I have
both on the stocks.
I have not actually used this code, but I adapted it from my 'proof of
concept' program for adding DIM LOCAL to Basalt. Unfortunately I have
adapted it too far in an attempt to tidy it up, and I have learned
something fresh about BASIC.
In PROCtest I have made L%() local, but it is so far undimensioned.
Then in FN_DIM_LOCAL I have dimensioned the array, but it is marked as
a local array so it only only exists within that FN; on return to
PROCtest it is lost. So you must not use FN_DIM_LOCAL, but do all the
work in PROCtest:
DEFPROCtest
LOCAL block%,L%():DIM L%(n%):block%=!L%
REM if n%=(bytes%-15)/4 it is like DIM LOCAL
...
ENDPROC
Sorry about that. ;-(
I quite like that. I think my exposure to C persuaded me to use a
single-character operator, but your PTR() is similar to VARPTR() in
other BASICs.
> Then I looked at BB4W and saw that you do it more simply and
> pass just the l-value.
Yes, that seemed more consistent somehow. As far as strings are
concerned I would want some way to manipulate the length byte/word,
and if the 'address of' operator returned the address of the string
itself (rather then the address of the descriptor) you couldn't do
that.
Another thing is that (in BB4W at least) the l-value remains constant
but the string address can change if its length changes, so I'd rather
the address-of operator/function returned the thing that remains
unchanged for the lifetime of the string.
> So you must not use FN_DIM_LOCAL, but do all the work in PROCtest:
> DEFPROCtest
> LOCAL block%,L%():DIM L%(n%):block%=!L%
> REM if n%=(bytes%-15)/4 it is like DIM LOCAL
Argggh! I naturally assumed that your original code was tried-and-
tested, and having discovered that FN_DIM_LOCAL didn't work in BB4W
(for the reason you explain) I added that to my list of 'known
differences from BASIC V'. Now I discover that there isn't a
difference (in this respect) at all!!
Your revised code works on BB4W, except that the (bytes%-15)/4 needs
to be (bytes%-6)/4 to ensure enough space is allocated.
That is returned by LEN, and I did not think that you would need to
change it.
> Another thing is that (in BB4W at least) the l-value remains constant
> but the string address can change if its length changes, so I'd rather
> the address-of operator/function returned the thing that remains
> unchanged for the lifetime of the string.
That is a good reason. I was also influenced by my use of Basalt's new
types (entities). These go from l-value to an anchor word to the data
in the dynamic heap. So you might get !!PTR.
> > So you must not use FN_DIM_LOCAL, but do all the work in PROCtest:
> Your revised code works on BB4W, except that the (bytes%-15)/4 needs
> to be (bytes%-6)/4 to ensure enough space is allocated.
Sorry about the confusion - I was over-enthusiastic.
Obviously it's not a common requirement, but there have been occasions
when I *have* changed the length value (in BB4W). For example I've
occasionally wanted to access a character string (e.g. returned from
Windows) whose address and length I know but which isn't CR or NUL-
terminated:
!^fixed$ = address_of_string%
?(^fixed$+4) = length_of_string%
One must be careful not to attempt to modify fixed$ afterwards (!),
but it's a quick-and-dirty way of avoiding copying the string
somewhere else.
Another thing I've occasionally done is 'alias' a 4-byte string to an
integer (handy for things like FourCC values):
!^fourcc$ = ^num%
?(^fourcc$+4) = 4
Faster (though more dangerous) than:
fourcc$ = CHR$(num%) + CHR$(num%>>8) + CHR$(num%>>16) + CHR$(num
%>>24)
Note that in BB4W ^fourcc$ *creates* fourcc$ if it didn't previously
exist. To do the equivalent using your PTR(fourcc$) syntax I expect
you'd have to do fourcc$="" first.
That does look dodgy. ;-)
Basalt 0.98 has the function RETURN$, which /copies/ a string from a
buffer, either terminated by a control character or with a given
length. It also has RETURN$ as a statement that inserts a CR (or any
other character if needed) directly into the buffer so that the string
can be read as $buffer%.
> Another thing I've occasionally done is 'alias' a 4-byte string to an
> integer (handy for things like FourCC values):
>
> !^fourcc$ = ^num%
> ?(^fourcc$+4) = 4
>
> Faster (though more dangerous) than:
>
> fourcc$ = CHR$(num%) + CHR$(num%>>8) + CHR$(num%>>16) + CHR$(num
> %>>24)
Are there are possible uses for this in RISC OS for identity words such
as "TASK"?
> Note that in BB4W ^fourcc$ *creates* fourcc$ if it didn't previously
> exist. To do the equivalent using your PTR(fourcc$) syntax I expect
> you'd have to do fourcc$="" first.
I am not in a position to test this ATM, but the BASIC routine I have
used should create the variable if it does not exist, as BB4W.