localtime() is broken [might be Territory?]
Rick Murray (539) 13851 posts |
If anybody wants to try this themselves on older 26 bit systems, the modified CLib is here: http://www.heyrick.co.uk/random/CLib,ffa (module) It will probably identify itself as the same version as the one you have (if you’re using the PlingBoot updates) as it has been built from the same sources. The program to call gmtime() then localtime() is here: http://www.heyrick.co.uk/random/timefiddle,ff8 (absolute) It needs a suitable 26/32 bit neutral version of CLib. |
Steve Pampling (1551) 8172 posts |
Silly question but RPCEmu has a podulerom called syncclock, which unless told to butt out “syncclock 0” decides to “help” by adjusting the time to match the already adjusted PC clock. PS. Yeah textile sucks |
Rick Murray (539) 13851 posts |
It is calling the wrong SWI. It may 1 work okay if you specify a locale to the C library; however if you want to use the current system locale it will fail if you use any timezone other than the first one defined because the code only looks at the first one. It is much easier to read the current timezone offset and apply that without any other nonsense, but for some reason… 1 However given that it is the territory that supplies the locale information, you can only specify locales which are known to the system. Which is… |
Rick Murray (539) 13851 posts |
Help! Can I build an APCS-R application using the not-quite-but-almost latest version of ROOL’s DDE? I need to do some tests on CLib that predates the 32 bit neutrality; and I would prefer to be spared attempting to go through archive CDs in the hope of locating Acorn C v4. |
Dave Higton (1515) 3534 posts |
When DST is in force, what exactly should localtime() return? We’re currently in DST here in the UK. My Iyonix is set up for the UK. When I call gmtime(&t, &tms), tms.tm_hour is the UTC hour number, and tms.tm_isdst is 0. When I call localtime(&t, &tms), tms.tm_hour is the DST hour number (1 greater than the UTC hour number returned by gmtime()), and tms.tm_isdst is 1. My question is whether localtime()’s hour number (and all the rest, considering day rollover, of course) should already represent DST, in which case tms.tm_isdst is merely informational; or tms.tm_hour etc, should represent the non-DST time, and the tms.tm_isdst flag should cause 3600 minutes to be added conditionally. Differing interpretations of this are causing duktape to return a Javascript Date() value an hour ahead of reality at the moment. I’ve looked on the Internet, of course, but the answers I’ve seen are vague, not clear. I’d like to know what the relevant standards say. |
Colin (478) 2433 posts |
As I understand it it should return the local time ie dst and timezone are incorporated into hrs. tm_isdst tells you that dst has been added. Edit I should add that is_dst may be -1 if dst information was not available. |
Chris Mahoney (1684) 2165 posts |
For what it’s worth, it seems that taking the output of time() and passing it to ctime() has the same issue. The docs say that ctime() returns local time, but also that it’s equivalent to asctime(localtime()) so it makes sense that it’s broken too. I’m not using setlocale(), indeed I don’t know where to get a list of valid locales to try! |
Dave Higton (1515) 3534 posts |
That’s what I had understood too, but when I saw code in duktape.c that very deliberately adds 3600 seconds to the local time if localtime()’s tm_isdst is >0, I had to ask. I think it’s a coding error in duktape. It causes NetSurf’s Javascript Date() function to return a time that’s 1 hour in advance of reality. I haven’t seen any evidence that anything in RISC OS is broken, but I haven’t been looking very far or stressing anything. |
Colin (478) 2433 posts |
RISC OS looks broken to me, localtime isn’t adding the timezone – at least not in newer versions. The version I use in RPCEmu – which is old (RO 5.17 sharedclib 5.74) – correctly adds the timezone, the version on my iyonix (sharedclib 5.83) and pi (sharedclib 5.85) do not. DST gets added on all of them. Setting the timezone sets alarm correctly. I also note that the possible tm_isdst values are <0 (No DST info) 0 (DST not in operation) and >0 (DST in operation). Acorn C actually uses 32768 to indicate DST in operation. Edit |
Dave Higton (1515) 3534 posts |
I’m still using RO 5.22 on my Iyonix, and in any case I’m in the UK timezone, so I wouldn’t see any of these breakages.
32768 is a curious number to use to denote DST in operation, given the three interpretations (no info, not in operation, in operation). How big an integer does it use? |
Colin (478) 2433 posts |
4 bytes on RISC OS. I had thought that 32768 was used so that it worked on systems which use 2 byte ints but it doesn’t because then it would be negative. There will be some good reason. edit: It turns out to be the value returned from _kernel_osbyte(161,220,0) anded with 0×8000 which is the dst bit from cmos ram. |
Dave Higton (1515) 3534 posts |
Are we really saying that localtime() does not take account of time zone? That would be a non-conformant, broken version of localtime().
Is this statement available to the public? |
Colin (478) 2433 posts |
It does and it doesn’t.
At the beginning of this thread. |
Rick Murray (539) 13851 posts |
Yup. Simple used-the-wrong-SWI error, but ROOL wants a bit of regression testing on platforms that didn’t even correctly support alternative territoires/timezones so… I just find it comical that introducing zero page impossibility can happen but fixing an obvious bug is harder. ;-) So…as a person with UK/CEST, I build my own ROMs so I can fix it. No good all the C programs being an hour out……. |
Dave Higton (1515) 3534 posts |
I haven’t ploughed my way through all of this thread and Rick’s white paper, so I apologise in advance if anything following is out of date. “Territory” conflates three things that are not always linked: language, time zone and keyboard. Each of the three should have its own settings. If a Territory command is issued, it ought only to be done so by a canonical user of that territory; e.g. someone resident in the UK who speaks English and uses a standard UK keyboard. So a Territory command should be regarded as optional. If one is issued, all it should do is set the three things, each of which can be overridden by other commands. The challenge, surely, is to make the OS accept settings for each, independently of the other two. Language clearly needs a setting, and could perhaps benefit from some optional fallback languages in priority order, so that creating a set of resources doesn’t have to be “all or nothing”. Time zone needs settings for the basic offset, and either rules for DST start/stop/offset, or start/stop/offset for a this year. A list for more than one year might be nice. There doesn’t seem to be much to say about keyboard. |
Chris Mahoney (1684) 2165 posts |
Given the following considerations,
I believe that localtime() should use the time zone configured through Configuration, even if the territory is set to UK. That is exactly how new users are going to configure their time zone (just like I’ve done myself) and so C applications – and therefore localtime() – should respect that setting. I agree with Rick and others; the current implementation is broken. |
Chris Mahoney (1684) 2165 posts |
I’ve done a little more experimentation. If you get the time with OS_Word 14,3 and then convert it to a string with Territory_ConvertStandardDateAndTime then it returns the correct local time. This works with both Pi RC14 and 3.10 in ArcEm. It’s not as convenient as calling localtime() but it works, and won’t require the customer to install an updated CLib. |
Rick Murray (539) 13851 posts |
Though that shouldn’t be a barrier to fixing CLib… |
Chris Mahoney (1684) 2165 posts |
Indeed. |
Rick Murray (539) 13851 posts |
Following a prod from ROOL, I have added some tests regarding the standard ROM module version of CLib with RISC OS 3.50*Help SharedCLibrary Module is: C Library 4.58 (10 Feb 1994) *TimeFiddle gmtime() says : Sat Apr 23 16:44:21 2016 localtime() says : Sat Apr 23 18:44:21 2016 *Status TimeZone TimeZone +1:0 *Status DST BST * RISC OS 3.70*Help SharedCLibrary Module is: C Library 4.84 (04 Jul 1996) *TimeFiddle gmtime() says : Sat Apr 23 17:10:34 2016 localtime() says : Sat Apr 23 19:10:34 2016 *Status TimeZone TimeZone +1:0 *Status DST BST * And…?I am not currently able to test the updated CLib. I ran a Clean / Clean All in Builder, then I manually ran “MkLibs26” in …Sources.Lib.RISC_OSLib but the resultant module does not work (on RISC OS 3.5; same with 3.7): *RMLoad CLib2632 *TimeFiddle Error: Internal error, trap while in trap handler: Internal error: abort on data transfer at &02169CC8, pc=72169CC0: registers at 00008714 (Error Number &800E00) * It was build with the BCM2835 environment, maybe some 32 bit stuff crept in (check out the ridiculous value of PC)? I can’t build using the IOMD environment, throws a lot of errors trying to find <Machine> something or other, so I’m rebuilding using the CTools environment. Will that work? |
Rick Murray (539) 13851 posts |
While building the libraries, I noticed a peculiar warning, so I went to see what was happening, and stumbled across something really rather horrible… The warnings:
Okay, brace yourself: void txtmisc_select(txt t, txt_index a1, txt_index a2, txt_index a3) { txt_index a4; txtscrap_setselect(t, (a1 < (a4 = (a2 < a3) ? a2 : a3)) ? a1 : a4, (a1 > (a4 = (a2 > a3) ? a2 : a3)) ? a1 : a4); } |
Rick Murray (539) 13851 posts |
Okay, we’re on to something, maybe. Diff says the new CLib2632 is different, and it is marginally larger. Let’s see if it works. |
Rick Murray (539) 13851 posts |
RISC OS 3.50*Help SharedCLibrary Module is: C Library 4.58 (10 Feb 1994) *TimeFiddle gmtime() says : Sat Apr 23 18:49:43 2016 localtime() says : Sat Apr 23 20:49:43 2016 *Status TimeZone TimeZone +1:0 *Status DST BST *RMLoad CLib2632 *Help SharedCLibrary Module is: C Library 5.88 (29 Feb 2016) *TimeFiddle gmtime() says : Sat Apr 23 18:49:59 2016 localtime() says : Sat Apr 23 18:49:59 2016 * So the modified softload version of SharedCLibrary seems to break the ability of CLib to deal with timezone offsets, which is bizarre given that the SWI used returns the valid offset. However, it is not the modification. CLib has been thusly broken awhile: *RMLoad CLib543 *Help SharedCLibrary Module is: C Library 5.43 (05 Sep 2002) *TimeFiddle gmtime() says : Sat Apr 23 18:56:27 2016 localtime() says : Sat Apr 23 18:56:27 2016 * So given this test, on RISC OS 3.5 at least, the modified version of CLib is no worse than the currently distributed version(s). 5.43 isn’t a new one, I wanted to pick a middle-of-the-road one for testing. The latest I have on the emulator is 5.83, it behaves in the same manner. It is a problem with RISC OS 3.5. RISC OS 3.70First is ROM CLib, then softload 5.43, then new modified CLib. *TimeFiddle gmtime() says : Sat Apr 23 19:30:25 2016 localtime() says : Sat Apr 23 21:30:25 2016 *RMLoad $.!Boot.Resources.!System.Modules.CLib543 *TimeFiddle gmtime() says : Sat Apr 23 19:31:05 2016 localtime() says : Sat Apr 23 21:31:05 2016 *RMLoad $.CLib2632 *TimeFiddle gmtime() says : Sat Apr 23 19:31:19 2016 localtime() says : Sat Apr 23 21:31:19 2016 * “TimeFiddle”, remember, was built using C v3, so it is old APCS-R. For the sake of completeness, though this ought to be obsolete in the same sense as Windows 3.xx: RISC OS 3.10*Help SharedCLibrary Module is: C Library 3.99 (23 Apr 1992) *TimeFiddle gmtime() says : Tue Apr 23 19:41:43 1996 localtime() says : Tue Apr 23 19:41:43 1996 *RMLoad CLib543 *TimeFiddle gmtime() says : Thu Dec 21 13:04:56 1995 localtime() says : Tue Apr 23 19:41:54 1996 *RMLoad CLib583 *TimeFiddle gmtime() says : Tue Apr 23 19:43:59 1995 localtime() says : Tue Apr 23 19:43:59 1996 *RMLoad CLib2632 Internal error: undefined instruction at &01828D38 * It is possible that there is an ARMv4+ instruction lurking in my build of CLib, which is why it won’t load. But, hey, it can’t be any more batpoop insane than the results of CLib 5.43. Interesting that v5.83 behaves differently. It isn’t a one off, I’m switching back and forth between 5.43 and 5.83 and the results are entirely consistent. Something changed here between 2002 and 2014… If somebody can build me a version of CLib that works on 3.10 (with this modified time.c file), I’ll give it a whirl… If you want to run your own tests, the module will be here for a short while: http://heyrick.ddns.net/files/CLib2632.ffa |
Rick Murray (539) 13851 posts |
Okay. Done some more testing. First up – it may not work on RISC OS 3.10. The CMOS RAM location 220 for !Alarm options (including DST flag) was introduced with RISC OS 3.50; so it may not be present within RISC OS 3.10. There is a way that DST/NoDST is stored, but there’s nothing obvious in the PRM of CMOS locations to indicate how. I’m not going to further test this because:
At the very least, the behaviour now, if it is broken, should be no more broken than the current versions of CLib… Secondly – the entire RISC OS 3.50 problem, and its refusal to actually support timezone differences, was a giant red herring. I dropped a load of printf() statements into CLib and ran the test program, and here’s what turned up:
On RISC OS 3.50, the call to |
Jeffrey Lee (213) 6048 posts |
http://www.phlamethrower.co.uk/misc2/clib26.zip That should be good for all supported 26bit versions of RISC OS (i.e. 3.1+) The trick for building your own version is to use the PlingSystem product (which builds the !System distribution for 26bit machines) – but it doesn’t look like that’s one of the standard source tarballs so unless you can fetch it directly from CVS you might have a bit of trouble getting it to work. It builds one version of CLib, which supports APCS-R and APCS-32. No need to use archaic versions of the C compiler! |