localtime() is broken [might be Territory?]
David Feugey (2125) 2709 posts |
I agree too :) |
Steve Drain (222) 1620 posts |
There is an element of deja vu here, but this is slanted towards time rather than languages/numbers/currencies. I agree that the Territory concept seems to fall short of what is required. However, I seem to recall that it was first conceived as a Rom module for machines that would be sold both inside the UK and overseas, each of which would be a separate version. It would provide reasonable defaults for a system out of the box. This has had onward implications. After the last flurry I wrote a suite of ‘Region’ programs that allowed independent setting and configuration of most of the factors that were of concern. I do not know Windows 7 or 8, but a good look at the ‘Regional and Language’ dialogue in XP suggests that its progammers might have come up against some similar problems. I never put the final polish on the suite, for consideration here, for two main reasons. First, the Configuration plug-in and it sub-programs are written using Basalt. Second, I used soft-loaded Territory modules that were modified in situ. Nevertheless, the whole thing was great learning experience. ;-) The modified module method was quite simple, because you can identify the various tables from the values returned by SWIs. I have done a quick test, and it is certainly possible to change the default time zones and names this way. So you could configure the France Territory on the fly with GMT amd +0 instead of CET and +1. This is more complex than that simple statement, and I do not think modifying modules is likely to be an approved technique, but I offer it as a possibility, because it does not need a whole new system and should be backward compatible. |
Rick Murray (539) 13851 posts |
Yup. ;-)
That part gets the largest paragraph in the document I linked to, mind you. ;-)
Which no doubt made some sort of sense in 1992 (although I suspect the two Canadas, the one Switzerland, and the Dvorak keyboard as a new territory should have hinted that the spec was going to fall apart sooner or later).
It is “something like that” that I would have in mind for the user-facing interface.
? Aren’t you supposed to be promoting Basalt? ;-)
Ah. Well… Doesn’t the necessity to load a soft-load module and binary-patch it in-situ suggest something of a grand limitation of the original design? Anything that needs to be poked like that is either a game the user wants to cheat at, or badly designed.1
Doing it the other way around? Less so. The UK module holds the timezone in four bytes as both are three characters long. Pasting in CEST would require the MSB of whatever follows to be a null to act as a string terminator. That’s icky. Certainly, adding additional time zones would be non-trivial. I guess you could allocate some RMA, build the table there, then fudge the pointers in the module…but that’s about the time to concede that there ought to be a better way!
I don’t really fancy designing and creating a whole new system – but the more I try to do non-UK, the more Territory gets in the way.
This is a big concession that I made. A lot of stuff (all of the ResFind type programs, for instance) make the assumption that territory name equals language. This is why we all stick our resources in “UK”. As awful as this may be for any sensible attempt at internationalising things, it’s what we are stuck with at the moment, and I fully acknowledge that my idea (and its implementation) might be the best thing ever, me on the front of Time magazine, etc – but it won’t be worth a damn if it breaks everything written prior (which, let’s face it, will be everything). As much attention needs to be paid to faking something for compatibility as making something new. There’s no if, but, or maybe about that. 1 Or we’re doing nefarious things with copy protection, the less said about that….. |
Steffen Huber (91) 1953 posts |
Actually, the original ResFind used the “Country” as the default, not the territory name. And, using ResConf, the user had an easy way to choose per-app language. Which was an excellent reason for many developers to choose ResFind as an i18n vehicle instead of inspecting the territory. |
Chris Mahoney (1684) 2165 posts |
Well, I made a new territory cloned from Australia, and everything seems to work properly. *Time gives the correct time for both timezones, and localtime() as expected gives the correct time for the first one in the list (I haven’t applied Rick’s fix). A quick check of a few apps didn’t turn up any problems; the apps appeared in English as expected, presumably using UK resources. The only problem I had was that I had to “piggyback” on top of an existing territory because I didn’t know how to add a new one; editing RiscOS.Sources.Programmer.HrdSrc.hrd.Countries doesn’t appear to be sufficient. Ideally I’d ask for one to be allocated properly but I’m just trying to test things at this stage. PS. I just realised that I haven’t mentioned it yet: I’m in New Zealand and there is no existing territory number. Bizarrely there’s one for Maori (NZ’s other official language) so I hijacked that one for testing. |
Steve Drain (222) 1620 posts |
It was a guide for me, but it cannot be copied. First, we have to fit into the RO Configure protocols. Second, Windows gives primacy to the language, so there are choices for German (Switzerland), French (Switzerland), Italian (Switzerland) and Romansh (Switzerland) rather than Swiss1, Swiss2, Swiss3 and Swiss4.
I would, but it is a third-party resource and will not be accepted for system components. ;-(
Yes, but bear in mind that the module being patched is subsidiary to the Territory module and that it is largely a data repository.
I was very careful to choose and example that worked, so you caught me out there. If this were a reasonable method to adopt, it would be quiet simple to change the module format so that strings were in , say, 12-byte buffers.
I have no idea how this can be resolved in retrospect. Like you, I can see a way to design things for the future – my Obey$Path macro-variable works for me – but I have only the haziest ideas about making that work with ‘UK’ etc.
Although you can make them different, by default they are the same, and share the same list. I understand that Terrirtory should normally take precedence. |
Sprow (202) 1158 posts |
It’s a little hard to pick out the content here amongst the angry mob shouting, a more calm and considered approach is generally what’s needed in engineering disciplines. setlocale() as of 5.20 accepts a named timezone to mimic (for example) Windows so you can even have one program running in two task windows in two different timezones if you want (!), you’ve not called setlocale() however A case in point: the two statements are correct – you can pass a named timezone to setlocale(), but in the original post it looks like setlocale() is not being called, if setlocale() isn’t called you get whatever the C library chose to implement.
I think there’s some confusion here because countries, keyboards, and alphabets are all (currently) allocated from the same creaking number space. As it happens countries map 1:1 to territories for those < 127 but the Dvorak allocations are keyboards. However, as there’s no configure command to store the keyboard it’s (currently) spoofed as a fake country. Some keyboards have leaked into the wiki too I see.
Looking back in CVS history it appears to have always done that. However, when Territory_ReadTimeZones was fixed to not adjust the lookup table based on timezone (which never really made sense, since things like CET and CEST are at constant offsets from UTC) it appears to have exposed a latent bug in localtime(). A bug in software? Bring me my flaming torch… With the C library extra care is needed
I don’t see any evidence of this in ticket 391.
The allocation of territory and country numbers is likely to be incomplete, for example if a flemish speaking commercial customer from Belgium commissioned Acorn to produce a translation of RISC OS for them why would they pay for all the work of a French and German translation too? Therefore, an absence of an allocation doesn’t mean such a territory couldn’t exist. Canada1 and Canada2 are probably the cleanest examples of what was intended, though I don’t think that infers needing two modules as that PRM reference suggests. Rolling a one module = one territory isn’t hard, the entry points are mostly just pointers to tables, and there’s plenty of examples to start from.
Agree – this has swerved away from a bug and more into design. However, in reading I don’t really see anything that wasn’t already captured in this thread which in itself repeats much of this thread so if there’s actually some new ideas it’s probably worth pasting them onto the end of one of those 2 threads so they don’t get lost. |
Rick Murray (539) 13851 posts |
Wow – about the only time Burns and Homer have been in agreement over something.
So you are saying that it is the responsibility of the application to handle timezone offsets because the C library is broken ? Note that
Quote: 7.23.3.4 [The localtime function] 1 #include <time.h> struct tm *localtime(const time_t *timer); Description 2 The localtime function converts the calendar time pointed to by timer into a broken-down time, expressed as local time. Returns 3 The localtime function returns a pointer to the broken-down time, or a null pointer if the specified time cannot be converted to local time. [source] Note the repeated references to local time. I would imagine an implementation that supports time zones but has a
Nothing. I say this because there is no indication in the CVS that it ever did it another way, so I can only imagine that this goes back to RISC OS 3.00 and in the intervening decades, apparently nobody else noticed. Wow. Of course, for completeness, I ought to write a small test program and try it on various emulated versions of RISC OS… Oh, and the SWI used is documented in the RISC OS 3 PRM, so it should be valid on everything that isn’t RISC OS 2.xx.
Of course, that’s what the allocations are for. However, as pointed out, there is the assumption that the territory name implies the language, which really ought to be “aided by the territory but apart from it”. This would allow combinations like UK/Welsh and France/Breton. Things that are not possible now without creating entirely new territories. Think also of Morocco and Lebanon, both could validly use French as a language. Or how many countries could use English as a language, and have their own regional options. The entire commonwealth for a start. Probably America too (I will worry about locali Timezone….that ought to be a separate module that just deals with time zones independently of any specific loaded territory. |
Steve Pampling (1551) 8172 posts |
Wrapping in timezone too, I’d offer UK, Australia, New Zealand, and the US as a prime example of spread of primary language use in disparate locations/regions/timezones. The different territory, timezone, language and keyboard use do need dividing. The question is what is the least disruptive change method? |
Chris Mahoney (1684) 2165 posts |
Perhaps this isn’t the best time for me to point out that Windows 8 is available in “real” English :) |
Rick Murray (539) 13851 posts |
@ Chris: So with their budget and market dominance, it only took ‘em 20 some years to recognise that Brits spell stuff differently. ;-) |
Chris Mahoney (1684) 2165 posts |
I don’t deny that it’s terrible :) Still, Microsoft is doing better than Apple; only iTunes and the “iDevices” have been localised. |
David Feugey (2125) 2709 posts |
Best solution is to separate all these parameters, because they are not linked.
Perhaps it’s possible to have a configure plugin that can assemble a territory module from all these parameters? So we keep the module, but give more flexibility to the users. |
David Feugey (2125) 2709 posts |
For example, here in France:
None of these parameters can be linked together. |
Steve Drain (222) 1620 posts |
I pretty well agree with your list of paramenters and I have written the substance of such a plug-in. However, there are some things to add, there are currently limitations and it is not yet presentable. Would anyone would use it? Would it be acceptable to fiddle with territories this way? Could third-party software be part of it? Should I work on this further rather than than just for fun? ;-) |
Steve Drain (222) 1620 posts |
@Rick I have been re-reading about territories in the RO3 PRM. I did note that there are several mentions of the CLib functions and their relationship to Territory SWIs. In each case it states that setlocale() must be called before using any of them. Is this relevant? |
Steve Pampling (1551) 8172 posts |
I read David’s suggestion of the Configure plugin creating a personalised territory module and thought that perhaps a multinational that picked specific settings information from a text file might be the way to go.
I’m sure developers are free to offer their work to be included in the general repository.
Since there’s no real money in these things, fun or sense of achievement is all there is. I say “Play away”. |
David Feugey (2125) 2709 posts |
Me for sure.
To be honnest, I don’t think so. But, evolution is better than revolution, so it seems to be the best way (IMHO).
Oh yes :)
A bit as MDF files. To provide predefined templates for example. Why not. Some 32bit tools to create keyboard and resources modules should be provide by default too (I’m not sure they are still available). |
David Feugey (2125) 2709 posts |
As tools to make pointers ans system sounds modules. A bit out of topic. |
Rick Murray (539) 13851 posts |
If you don’t explicitly call “During program startup, the equivalent of setlocale(LC_ALL, “C”); is executed before any user code is run." |
Sprow (202) 1158 posts |
A case in point: the two statements are correct […] setlocale() No, the two statements were pointing out a shock new feature in the OS that relate to localtime() that you might have been interested in. Clearly you’re not interested, I’ll stop wasting key presses. * is the change ISO9899 compliant?7.23.3.4 [snip] Good, it seems to be compliant. Remember there’s an equally large angry mob that chases after you for fixing bugs in the C library so it’s worth checking. * what happens if I softload the change on a pre RISC OS 5 machine?Nothing. I say this because there is no indication in the CVS that it ever did it another way. I think you’re only looking at the C library then, remember there are 4 combinations to test as the territory module has also changed so by my reckoning the current C library on an older territory (where Territory_ReadTimeZones changed its answer depending on the timezone CMOS) would still mask the localtime() problem. Unfortunately CVS only goes back as far as about 1996 so an empirical test will be best to cover back to 3.10 (which is the earliest version the C library is offered for). |
Rick Murray (539) 13851 posts |
Just looking at the bug listing and…
I am guessing that I can build a 26 bit version of the C library by running the “MkLibs26” file? All that this will (hopefully) show is that the change does not screw up the time on older machines. It won’t show up whether or not this issue even exists as for that we would need to have a 26 bit version of a territory with multiple timezones.
(my UK territory module has been modified to include CET/CEST) If so, I can try the result on RISC OS 3.70 (RedSquirrel) and… I might have to dig out “actual hardware” to test on RISC OS 3.10. |
Colin Ferris (399) 1818 posts |
Err – RSq runs 3.10 & 5.19/5.21 don’t know about RO6. |
Rick Murray (539) 13851 posts |
Oh, that’s good to know. I’ll have to see if I have some ROM images for that OS. Can’t now as I’m ripping a DVD for mom set in her home town, and that computer is using the keyboard and mouse that I’d normally use with the Pi. |
Rick Murray (539) 13851 posts |
Okay. Can’t try RISC OS 3.10. I have a ROM image extracted from !Archie (that works!) but when used with RedSquirrel’s A5000 mode (either as a 2MiB file or split into 4×512KiB) it causes RedSquirrel to crash. I have built a 26 bit version of my version of the CLib localtime() function. I have been sent some tweaks, but those are on my phone, not anything I can easily get over to RISC OS. Comparing the two, on screen, there is nothing that should alter the code behaviour in any significant way for these tests. The test program is as follows:
The results are: RedSquirrel – RISC OS 3.70 – UK territory, GMT timezone With standard 32 bit neutral CLib: *timefiddle gmtime() says : Mon Feb 16 18:01:17 2015 localtime() says : Mon Feb 16 18:01:17 2015 With modified CLib: *timefiddle gmtime() says : Mon Feb 16 18:11:43 2015 localtime() says : Mon Feb 16 18:11:43 2015 RedSquirrel – RISC OS 3.50 – UK territory, GMT timezone With standard 32 bit neutral CLib: *timefiddle gmtime() says : Mon Feb 16 18:15:41 2015 localtime() says : Mon Feb 16 18:15:41 2015 With modified CLib: *timefiddle gmtime() says : Mon Feb 16 18:17:32 2015 localtime() says : Mon Feb 16 18:24:45 2015 Yes – the times appear to differ by 433 seconds (7m13s). This appears to be consistent and does not occur with RISC OS 3.70. I do not have RISC OS 3.60 ROM images to compare. RISC OS 3.10 – UK / GMT Okay, finally got something running on RISC OS 3.10 (and it was painful, I’m using the !Archie emulator within an emulator – yikes!) and it is also exhibiting the 7m13s disparity; behaviour is as for the RISC OS 3.50 test. Now, to understand why I bother, here are the tests with RISC OS 5.21 using a modified UK territory and the CET (2nd) timezone. However, for the purposes of argument, the behaviour is identical for any territory with multiple timezones where the user has selected a timezone that is not the first one. Consider USA with Pacific time. RISC OS 5.21, UK territory, CET timezone Using last night’s RISC OS 5.21 territory and the CET (+1) timezone: gmtime() says : Mon Feb 16 19:20:25 2015 localtime() says : Mon Feb 16 19:20:25 2015 This is not correct. There is no way timezone +1 can match GMT. This occurs because the standard localtime() code looks at the first timezone defined and, well, pretty much ignores the rest (including which one is actually in use). The same test, using my older RISC OS 5.21, with patched localtime() function: gmtime() says : Mon Feb 16 19:36:45 2015 localtime() says : Mon Feb 16 20:36:45 2015 This is correct. It is asking RISC OS for the details of the current timezone offset, instead of making assumptions. Summary: Something is obviously acting in a peculiar manner to create the minor (7m13s) disparity on early versions of RISC OS. This isn’t going to be an emulator bug as it happens in RedSquirrel and Archie alike; while it works exactly as expected within RISC OS 3.70. This leaves is with a choice. Okay, it will require more testing on more platforms, however…
or:
That said, there is an option 3 that may be the preferred option:
Well, that’s what I did on a rainy Monday. ;-) PS: Textile sucks. I might have mentioned that before… |