OS_GetEnv
Martin Avison (27) 1494 posts |
I have used OS_GetEnv many times in programs to obtain the ‘environment string’ which is the command line used to start the program (if it was not started by OS_Module,2). However, I have found a case where it does not return what I expected… 1. Start WimpApp1 The returned environment string is the command used to start WimpApp2, not WimpApp1. Is this an OS bug, or is it an (undocumented) ‘feature’ of OS_GetEnv? If the latter, are there any suggestions how the OS command could get the full pathname for WimpApp1? |
Leo Smiers (245) 56 posts |
I do not know if it is a bug or not. I would suggest to make a copy of the string before you call wimp poll. For further reference you then use the copy. |
Clive Semmens (2335) 3276 posts |
If the documentation states it should return the environment string belonging to the program that started it, then it’s a bug. If the documentation doesn’t make it clear whether (1) each program has its own environment string, or (2) there is just one environment string that gets updated every time a program is called, then it’s ambiguous, and the only way to find out the behaviour is to try it – remembering that in such circumstances there’s no guarantee the behaviour will always be the same on different implementations (or, confusingly, possibly even on the same implementation). Leo’s solution is the obvious one, whatever the real situation. |
Martin Avison (27) 1494 posts |
Unfortunately it is not that simple. I can only change the command, not WimpApp1 – or when it calls the command.
The PRM says ‘reads some information about the progam environment’ but does not (to me) clarify which program. |
Jon Abbott (1421) 2651 posts |
If WimpApp1 is running a command that expects a specific environment string, then it should use OS_GetEnv when it loads, to store a copy of the string and then set it via OS_SetEnv immediately before executing the command. It was my belief the environment string is common across all apps. |
Martin Avison (27) 1494 posts |
But I can only change the command, not WimpApp1. :-(( |
Steve Pampling (1551) 8172 posts |
Why not set a variable1 with SetVarVal after WimpApp1 is run but before wimpapp2 and another variable2 after wimpapp2 is run? |
Martin Avison (27) 1494 posts |
I can only change the command, and have no control over any of the WimpApps – or how many or when they are run. |
Rick Murray (539) 13850 posts |
RISC OS is a single process system, so OS_GetEnv is valid and correct for the program that is running at the point of initialisation. Any behaviour that relies upon what that call returns must be done prior to any activity that could cause other programs to have started. As you want the pathname for WimpApp1, you should – at program start – extract the pathname from OS_GetEnv, and then copy it to a string buffer for later reference… |
Chris Evans (457) 1614 posts |
Either I or other posters are misunderstanding Martin. |
Martin Avison (27) 1494 posts |
To try to clarify: my command may be used in a BASIC Wimp Application (not written by me) but the command needs to find the path name of the original program for the wimp application. It may help if I say the command is *ReportError, which needs the path name to issue a Throwback. If GetEnv is only guaranteed valid in a wimp program until it issues a WimpPoll, then (to me) that should be clarified in the PRM, and I need to find some other way of doing what I need to do. |
Rick Murray (539) 13850 posts |
I’ve always considered the base PRMs to document basic RISC OS behaviour, with the Wimp to be a sort of complicated extension. There’s a lot of stuff the Wimp changes the way things work – there’s only one video context, font handle, what happens with multiple directory scans at the same time (or if something else changes the directory during), etc etc… As to what you need, I’m not sure. Maybe hanging on to the application starting messages? |
Martin Avison (27) 1494 posts |
After a bit more investigation I am now convinced that OS_GetEnv will return details of the last program started, not the current program. In s.kernel the SWI simply does so on return r0 is a fixed pointer to the kernel workspace for the command. r1 is the value of MemLimit from ‘ZeroPage’. r2 is a fixed pointer to ‘ZeroPage’ for the time it was started. I can see nothing Wimpish that would help, so as Rick says I may need to trap the starting messages, and do a GetEnv then. From what I can see, other Throwback handlers have made the same (wrong) assumption based on the PRMs so I am not alone, and I think the PRM certainly needs clarification. Interestingly, OS_WriteEnv says in the PRM and in the code that it is mainly used by debuggers, though its possible use eludes me. |
Rick Murray (539) 13850 posts |
Yup – one context.
A debugger program is not “started” in the traditional sense, it is loaded into the debugger, so WriteEnv is probably a lame way of faking the environment, instead of trapping the GetEnv SWI. |
Jeremy Nicoll (2099) 4 posts |
Wouldn’t it be better then if the BASIC interpreter stored the command used to start any instance of a BASIC program within its own working storage? After all, a programmer using C would expect the C runtime to provide command args etc – I presume that WIMP programs written in C would have the same problem /if/ they used GetEnv… but they have no need to? |
Rick Murray (539) 13850 posts |
CLib breaks any command line given into standard argc/argv combinations, while we run into the problem that BASIC is not directly executed, so the command is something like |
Jeremy Nicoll (2099) 4 posts |
But presumably at the point when the BASIC interpreter gets control, if it used OS_GetEnv it could see the correct command string as at that point no other program could yet have got control? |
Chris Hall (132) 3558 posts |
Correct. In my BASIC programmes, which are multi-tasking, I call GetEnv after Wimp_Initialise but before the first Wimp_Poll call. |
Steve Drain (222) 1620 posts |
I confess that I have always assumed the same, and the Basalt
In all my testing that has been the case, so there were no errors. The
That is certainly a solution, and one I may pursue for Basalt. For BASIC as originally written it would have been a significant chunk of memory, perhaps.
Which may be generally suitable for C programs, but RISC OS has parameter passing using identifiers and qualifiers. For that you need to use
Basalt’s |