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
<jn.nntp.scrap...@wingsandbeaks.org.uk> wrote: > Alan Adams <a...@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.
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.
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.
On 24 Oct, in article <50af779589New...@avisoft.f9.co.uk>, Martin <New...@avisoft.f9.co.uk> wrote:
> On 24 Oct, in article <c5a86faf50.Alan.Ad...@laptop.adamshome.org.uk>, > Alan Adams <a...@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.
Martin
-- Martin Avison Note that unfortunately this email address will become invalid without notice if (when) any spam is received.
> On 24 Oct, in article <c5a86faf50.Alan.Ad...@laptop.adamshome.org.uk>, > Alan Adams <a...@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.
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
> On 24 Oct, in article <50af779589New...@avisoft.f9.co.uk>, > Martin <New...@avisoft.f9.co.uk> wrote: >> On 24 Oct, in article <c5a86faf50.Alan.Ad...@laptop.adamshome.org.uk>, >> Alan Adams <a...@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.
In message <091027225...@arcade.demon.co.uk> j...@arcade.demon.co.uk (Jonathan Graham Harston) wrote:
> 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.
> 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.
Which is why I said:
> > 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
which wouldn't be the case if the subroutine calls something else - or creates variables, etc.
Alan Adams <a...@adamshome.org.uk> 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.
The trick, of course, is to use a memory management library. (Or a trivial binding to OS_Heap.)
Alan Adams wrote: > Jonathan Graham Harston wrote: > > 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. > > LOCAL temp%:DIM temp% -1 > > !temp%=a_value > > $temp%="a string" > > etc.
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
On Oct 30, 5:58 pm, Steve Drain <st...@kappa.me.uk> wrote:
> you can fudge a DIM LOCAL with a local array, but it is a bit messy.
> DEFPROC_DIM_LOCAL:LOCAL L%():L%=END-4:ENDPROC
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:
Richard Russell wrote: > Steve Drain wrote: > > you can fudge a DIM LOCAL with a local array, but it is a bit messy. > > DEFPROC_DIM_LOCAL:LOCAL L%():L%=END-4:ENDPROC > 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
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.
-- ; ,', * 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
Steve Drain wrote: > 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!
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. ;-(
-- ; ,', * 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
On Nov 1, 11:14 pm, Steve Drain <st...@kappa.me.uk> wrote:
> I have found that the ^ operator is > too difficult to use in the way Basalt works, but PTR is handy; so:
> address%=PTR(L%())
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.
Richard Russell wrote: > Steve Drain wrote: > > 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.
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.
-- ; ,', * 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
On Nov 2, 5:07 pm, Steve Drain <st...@kappa.me.uk> wrote:
> That is returned by LEN, and I did not think that you would need to > change it.
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:
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.
Richard Russell wrote: > Steve Drain wrote: > > That is returned by LEN, and I did not think that you would need to > > change it. > 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:
> 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.
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):
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.
-- ; ,', * 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
steve wrote: > > Jonathan Graham Harston wrote: > > > LOCAL temp%:DIM temp% -1
> 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.
I temporarily forgot about =END, as I was paraphrasing from some version-independant library code (eg mdfs.net/blib/ProgEnv)
-- J.G.Harston - j...@arcade.demon.co.uk - mdfs.net/User/JGH The most perfect world is an imperfect world as the imperfections give people a reason to strive to change it.