Immediate Mode
If I run sbrandy.exe with no program specified on the command line, it enters Immediate Mode as expected. But if I specify a program on the command line, and an (untrapped) error occurs during execution, it exits the process altogether (so, for example, I cannot use Immediate Mode to help with debugging, e.g. by PRINTing variable values). Is that expected? Is there a way to make it enter Immediate Mode if an error occurs?
Edit: Forget it, I found the answer myself: I need to specify -chain progname not just progname. Not sure that's intuitive, but it works.
Edit: Forget it, I found the answer myself: I need to specify -chain progname not just progname. Not sure that's intuitive, but it works.
0
Comments
-
Use
sbrandy -ch programname
This CHAINs the program, dropping to immediate mode on program exit (unless QUIT or *QUIT is encountered). This is also true for the "full fat" SDL build.0 -
This CHAINs the program, dropping to immediate mode on program exit (unless QUIT or *QUIT is encountered). This is also true for the "full fat" SDL build.
Yes, I found it myself (I edited the post, but evidently you didn't see the edit).
What's the thinking behind this behaviour? None of my BASICs work that way, they always enter Immediate Mode on an error; the only way to exit the process is with QUIT (or equivalent). When might one want to quit the process just because an error occurs, throwing away any diagnostic information?
0 -
Richard_Russell wrote: »What's the thinking behind this behaviour? None of my BASICs work that way, they always enter Immediate Mode on an error; the only way to exit the process is with QUIT (or equivalent). When might one want to quit the process just because an error occurs, throwing away any diagnostic information?
It's inherited behaviour from upstream, and it follows other UNIX scripting languages that exit once the script (program) exits, and is behaviour I have made use of in scripts at work.0 -
It's inherited behaviour from upstream, and it follows other UNIX scripting languages that exit once the script (program) exits, and is behaviour I have made use of in scripts at work.
I notice that you also have a -quit <prog> option, how does that differ from just specifying the program to run?
0 -
It's about time I upgraded my copies of BBCSDL and BB4C! The flag that determines whether or not the interpreter exits by default is set somewhere in (I think) brandy.c, the -quit option allows you to explicitly say you want it to quit irrespective of how it has been compiled.0
-
-
Currently, any exit due to an error has exit code 1, but it could make sense to change that to ERR+1 - why +1? Exit code 0 is success, and returning 0 for an untrappable error would not be good...
Edit: I had forgotten, a program can also set its own exit code as a parameter to QUIT, which if not supplied, is zero.
Edit 2: I've gone ahead and implemented this. It'll be in tonight's nightlies.0 -
the -quit option allows you to explicitly say you want it to quit irrespective of how it has been compiled.
But I will look into the possibility of adding a -quit switch which would override the default behaviour, and instead quit in the event of an untrapped error occurring or exiting to immediate mode.
If I do, it will only be in the Console-mode editions. Personally I don't think it's right to quit-on-error in the GUI editions because you don't see any error message displayed, the app just quits unexpectedly with no indication why.
Try specifying in the brandy.exe command line a program which fails immediately, because of an error in the first few lines. I don't think you'll like the effect!
0 -
Just to note, there's a convention in Unix shells to return 128+exit code. Might possibly be less confusing than an off-by-one approach?0
-
I understood the exit code to be 128+signal, so a SIGSEGV causes an exit code of 139 for signal 11.
I could do an off-by-256 or off-by-1024?
Regarding Richard's possibility of adding '-quit- to his console version, that would certainly make it useful as a scripting language host that could then run a job written in BASIC via Cron, a web CGI etc, where the script is expected to exit upon completion. Also, to that end Matrix Brandy will, if it encounters a line beginning with #! at the start of the file, it is completely ignored and processing continues from the next line.0 -
Yes, sorry, signal value + 128. But it does seem better to me to add a nice power of two. (Edit: one is a power of two but I mean a larger one!)
Making BBC Basic more readily usable for scripting sounds like a good thing.
0 -
Regarding Richard's possibility of adding '-quit- to his console version, that would certainly make it useful as a scripting language host
But of course there's no point in ever using my BASIC in preference to yours in such an application. Those few advantages which my interpreter has over Matrix Brandy are all related to the GUI features (such as the ability to output proportional-spaced text or anti-aliased graphics).
As far as I'm aware, with the extensions you have added, the console version of Matrix Brandy does everything that the console versions of my interpreter do, if not always in a fully compatible way. Given that yours is also much faster, it's a no-brainer that it would be used in preference to mine.
0 -
Except structures0
-
I should add that my interpreter requires any file specified on the command line to be in BBC BASIC 'internal' (tokenised) format, it cannot run a plain-text file specified that way. That means any scripting application will require a tokenisation step, which could automatically append the QUIT.
0 -
Except structures
1 -
Yes, sorry, signal value + 128.
Because (in my BASICs, at least) this is already handled entirely differently from the other errors - because it is non-trappable - it seems to me that it can perfectly reasonably be treated as a special case in respect of exit code too.
So the approach I will adopt, if I implement it at all, will be to set the exit code to the ERR value (which seems the most obvious and natural thing to do) for all trappable errors, but to (probably) 256 or 512 for 'fatal' errors.
0 -
There's a wee complication, exit codes are the least significant byte of an int, so only values 0 <= ERR <= 255 are possible. 255 seems the most obvious choice then for ERR=0. However, some RISC OS-originated errors have ERR > 255.0
-
There's a wee complication, exit codes are the least significant byte of an int
Incidentally ERR = 255 is 'Unknown error' or 'Unsupported' in my versions of BASIC, and is for example issued when attempting to use EXT# as an l-value in BBCSDL.
0 -
Richard_Russell wrote: »Not in Windows they aren't, I can set an exit code of 256 or 512
- Terminating the program with END or STOP sets the exit code to 256.
- A 'fatal' error (ERR = 0) sets the exit code to 512.
- Other (trappable) errors set the exit code to the ERR number.
It's possible that in Linux the 256 and 512 codes will be seen by the shell as zero (seems pretty stupid to me) but there must be a way of getting at the 'real' number because the return value of main() is int not unsigned char!
0 -
From the man page for exit(3):
SYNOPSIS #include <stdlib.h> void exit(int status); DESCRIPTION The exit() function causes normal process termination and the value of status & 0377 is returned to the parent (see wait(2)).
It seems to be something buried deep in the system, and a quick Google search doesn't pull up any other UNIX offering exit codes outside the 0-255 range. It's why my tweak to reflect ERR in exit codes uses 255 if ERR=0, as to me it doesn't make sense to use a value that could be interpreted as success for a fatal untrappable error.
In Matrix Brandy, you can pass an exit code to QUIT, without one it will exit with 0. Similarly, when a program is run with -quit specified or implied, END will also result in exit code 0 but STOP (untrappable ERR=0) will result in exit code 255. Under Windows using STOP to end a program reporting an error condition and END (or QUIT) for a success condition is nicely portable - but since you've chosen exit code 256 this is unfortunately not portable to Linux or other UNIX-derived systems.0 -
From the man page for exit(3)...
Presumably the purpose of exit() is to allow you to abort a process at a point when the stack has not been unwound, for example inside a loop or function, when return would not have that effect. I never need to do that.
It seems I was right about being able to access the full 32-bit value in Linux, albeit that it's not very straightforward.to me it doesn't make sense to use a value that could be interpreted as success for a fatal untrappable error.
It seems to me eminently sensible to return a code which is distinct from 'success' (0) and all the possible trappable errors (1-255); 256 or 512 fulfil that requirement. That they can't be easily distinguished from zero in a Linux shell doesn't worry me, so long as they can be in Windows (trivial) and with some effort in Linux.STOP (untrappable ERR=0) will result in exit code 255.
The reason for this is that STOP is principally of value when debugging, so you want it to change the global state as little as possible. That's why it doesn't close any files, nor change the value of ERR.
I think this reflects what the BBC decided should happen way back in 1981, but isn't how Sophie implemented it. Even in the original BBC Micro User Guide it says "... STOP prints the message 'STOP at line XXXX' on the screen, otherwise the effect is identical to END".
0 -
Fair enough about STOP.
Being able to extract the full return code is only possible, from reading that Stack Overflow thread, if your process is called from another one where you can do that extra work. From the shell, or a shell script it won't be possible, be it Linux, Raspberry Pi or a Mac (unless Apple are ignoring POSIX on this), only on Windows will it work.0 -
Being able to extract the full return code is only possible, from reading that Stack Overflow thread, if your process is called from another one where you can do that extra work.
Until about a week ago nobody had ever suggested to me that it might even be useful to quit from BBC BASIC on an error, let alone provide a mechanism for discovering what that error was! That's despite me having made available BBC BASIC interpreters that can be run from a command line for something like 40 years!
In almost every circumstance I can imagine it's actually better to stay in the interpreter (in immediate mode) than to quit, because far more diagnostic information on the cause of the error is available. You can interrogate the line number, print variables, check memory usage, experimentally call PROCs and FNs directly etc., none of which is available once the process has exited.
0 -
I guess it rather shows (again!) that I'm coming at this from the point of view of a Unix/Linux sysadmin who does scripting for a living And yes, there is a mobile network here that has some scripts, called by cron, that are written in BASIC and run in Brandy. If course when developing them I would be using the -chain (or -ch) option for it to stay within the interpreter on error, but the last thing I want it to do is hang in the interpreter, especially when run non-interactively, if something goes wrong. I capture the output (it any) to a log file, which can be examined for clues before I did back into the code to identify what went wrong.0
-
the last thing I want it to do is hang in the interpreter, especially when run non-interactively, if something goes wrong. I capture the output (it any) to a log file, which can be examined for clues before I did back into the code to identify what went wrong.
This is precisely why I've never considered automatically exiting the process on an error to have any significant value: you have always been able to achieve this trivially by inserting ON ERROR QUIT ERR at the start of your program! If you really want a command-line option, you can do this:IF INSTR(@cmd$, "-quit") THEN ON ERROR REPORT : QUIT ERR
To me, using BBC BASIC code to determine whether or not your program exits on error is far more in the 'spirit' of the language than some command-line incantation. This will continue to be the only way to do it in BB4W and BBCSDL.
0 -
I'm coming at this from the point of view of a Unix/Linux sysadmin who does scripting for a living
0 -
I certainly wouldn't call myself a better programmer (if I was, I'd have got structures working already!), and what you have with your code is nothing short of amazing.
Indeed, just yesterday I've been playing with some historic BASICs of yours now that I have PiTubeDirect running on my Master 128, both Z80 as ROM and under CP/M, and for the Master 512.0 -
if I was, I'd have got structures working already!
Structures aren't complicated. Creating them is more work than accessing them, since the latter largely shares the same code used to lookup ordinary variables (i.e. scanning a linked list). The only significant difference is that whereas in the main variable lookup the 'pointer' field is the absolute address of where that variable is stored, in the case of a structure it's the offset from the start of the structure.
Creating structures is a fair bit of work, but is very similar to creating arrays. The main difference is that (in my BASICs at least) arrays have a single pointer - the data always follows immediately after the descriptor - whereas structures have two pointers - one to the descriptor and the other to the data.
As far as I remember, I developed structures by initially creating them with BASIC code and then getting the code to read and write them working. When that was working I added the code to make them LOCAL and pass them to functions. Only when all that was working did I extend DIM to create them.
I found that staged approach made the whole thing much easier.1