AmigaOs Version 45 new features: The BB2 contributes a new AmigaOs shell segment, extending the features of the new console driver of Os 3.9. Amongst various bug fixes of the V40 shell segment, quite some new features have been added. ______________________________________________________________________________ It can now be tested whether a certain variable has been set; the shell introduces for that the $? token which returns 1 if the variable has been defined, and 0 otherwise. Hence, echo $?a prints 0 unless a has been "set" before. The related token $?? tests whether a variable has been defined as a global variable. Some shell commands have been extended, others have been added. Please check the documentation in this drawer for more information about the new and improved shell commands. Variable names: The concept of variable names used to be quite broken in pre 45.5. Release 45.5 introduces a strict and consistent parsing of variables that should be hopefully backwards compatible without causing (too many) inconsistencies. A variable name is either: A dollar sign, followed by a sequence of alpha-numeric characters. A character is alpha-numeric if it is either a digit ('0'-'9'), a letter ('A'-'Z' or 'a'-'z') or a national character (codes 0xa0 and above). -or- A dollar sign, followed by a character sequence enclosed in braces. The name of the variable is the string within the braces without the braces itself, i.e. $a and ${a} refer to the same variable. A dollar sign may be escaped by a single star, no matter whether it appears inside or outside of quotes. Note that this is different from escaping of " and * itself which is required only within quotes. Therefore, the following strings represent variables: $a $ß $9äöü ${a} (note that this equals $a) ${ a } ${ >a} ${*a} ${a;comment} (this is the variable of the admittedly strange name "a;comment", ; does *not* act as a comment introducer within braces. "**$a" The name of the variable, preceeded by a * sign. The * in front of the second star escapes its function as $ escape character. The old shell choked on the last examples "successfully". The following sequences are NOT variable names *$a The string $a instead "*$a" The string *$a. The * escapes the $. Since backticks are always expanded first regardless of the remaining shell syntax, you may need to escape them by asterisks, even within braces. Hence, ${`echo hi`} refers to the variable "hi" ${*`echo hi*`} addesses the undoubtfully strange variable named "`echo hi`". Note that here backticks are part of the variable name. To set this variable, you would have to use: set "*`echo hi*`" foo -- New for 45.3: The interpreter name of the "magic interpreter cookie #! and ;!" in script files requires now quoting should it contain spaces. See below. -- Commands in double quotes are no longer searched in the resident list, neither from the alias list. Hence, 1> "Assign" really means "C:Assign" or any other Assign program from the PATH, but not a resident version of Assign. Therefore, 1> "CD" RAM: will fail because no external version of "CD" can be found. Command line parsing has been reworked a lot. The shell uses now the following mechanim: 1) Expand all backtick sequences in a first step. Note that this implies that a possibly backtick'd command gets expanded as its first step. 2) Get the first argument, possibly quoted, containing spaces. 3) If not quoted, check for aliases. If it is an alias, expand the alias by moving the remaining arguments at the position of the [] sequence, or at the end of the alias text. If this happens, steps 1)..3) are repeated, possibly expanding backticks of the alias. 4) Expand variables. 5) Check for implicit commands: CD,RX,EXECUTE,#!-Scripts, $VIEWER for datatypes. If so, move the command in front of the arguments. I better don't describe the pre-V45.1 method.... Note that the above allows backticks as command sequences and (canonical usage of) backticks in aliases, unlike pre-V45: 1.SYS:> `echo "List"` will generate a directory listing. It also allows recursive aliasing: 7.SCSI:> alias hi ho 7.SCSI:> alias ho echo "HoHo!" 7.SCSI:> alias hi ho ho echo "HoHo!" 7.SCSI:> ho HoHo! 7.SCSI:> hi HoHo! 7.SCSI:> As a special anti-hack, an alias is at most used *once* in an expansion. That is, 7.SCSI:> alias gnu "gnu is not unix" 7.SCSI:> alias gnu gnu is not unix 7.SCSI:> gnu gnu: Unknown command 7.SCSI:> will not try to expand "gnu" (again, it is expanded once), as you see. Backticks and aliases mix now nicely. Note that you need to escape backticks by * in the alias declaration to avoid that they get expanded on the alias line immediately: 7.SCSI:> alias ver version "*`which []*`" 7.SCSI:> alias ver version "`which []`" 7.SCSI:> ver list list 43.4 7.SCSI:> Besides various code improvements of the resident commands, "setenv" got a new option (thanks, Stephan!), so did unsetenv setenv foo SAVE hi will also place the contents of the "foo" variable into ENVARC:, making it reset-resident. Furthermore, "path" was improved by the "Head" option which moves new directory components to the front of the list. New directory commands PushCD, PopCD and SwapCD have been added, study their documentation for details. For other code modifications, study the history file. -- Shell V45 re-introduces the handling of the "h" bit. Should it find a command with "pure" and "h" bits set, it makes the command resident automatically. Note that this is (again) the V39 behaivour. Note that "h" is for "hold", not for "hidden". The idea of this feature is that some commands can be made resident automatically within the startup sequence just by using them. Note that you cannot yet boot from the new shell. The shell does no longer limit command lines to 512 characters. Command lines can now be unlimited in size, provided the command itself is smaller than the AmigaOs file name size limit (107 characters). The Shell will now auto-expand all of its internal buffers if required to do so. Furthermore, it uses now memory pools for this kind of administration. Similar limits to the length of shell variables have been dropped as well. The shell offers now extended "script" support. In case a script file - i.e. a file whose "s" and "e" bits are set - starts with either the magic characters "#!" or ";!", the string following this magic cookie is understood as the path to a command parser that shall execute this script. Hence, what we have here is more or less Un*xoid command interpreter logic. Note that ";!" was chosen as additional introducer because the Amiga shell uses ";" as comment, not "#". If no "#!" or ";!" is found, the script is parsed as usual by "Execute", as if these scripts would start with ;! EXECUTE at the top. Should the path of the command interpreter contain any spaces, it should be escaped by quotes. Added support for "file browsing". To be able to use this, set the variable "VIEWER" to the path of a program that is able to display registered DataTypes. For example, the following line in S:Shell-Startup will do this for you: set VIEWER MultiView If the shell encounters now a file as first argument that has its "e" bit cleared (!) and is parsed and recognized as a data- type by the data types system, the viewer command is run. NOTE: It is important that "e" is cleared. Otherwise, the shell tries to load the file as an executable and not as a "displayable" file. Most Amiga editors do *not* clear "e" when saving text files, unfortuntately. Hence, if this feature seems to fail, you should check the proper flags setting first. Added support for "stderr" redirection. For this purpose, the V45 shell introduces three new redirection symbols: *> filename : redirects stderr to a file *>> filename : appends output to stderr to a file *>< : redirects stderr to the same file that stdout goes into. The *> syntax was chosen because "*>" redirects the console whose file name is "*" for traditional reasons. Note that there are currently few programs that make really use of the "pr_CES" standard error stream. The shell will also assign the console to the stderr stream should this be inter- active. This does not work for plain files, unfortunately. Furthermore, if a file is run "in background" using the "&" syntax described below, the stderr defaults to the stdout if not redirected explicitly. If stderr is not a console, the console task of the new shell job is set to NULL disallowing console output. Added support for "script stdin" support similar to most Un*x shells. If the shell finds a "<<" redirection, the following symbol of the script is understood as an "end marker" symbol. All following lines up to a line starting with the "end" marker are then literally pushed into the command as "stdin" stream. Hence, the following example will display "Hello World!" by the "more" pager: more << End ;means: provide all the following lines as stdin Hello World! End ;stop scanning here. Unfortunately, the "<<" syntax does not mix with "run" for some internal reasons that are beyond the control of the shell. However, it mixes fine with the "&" syntax below. Added a new command line token, the "&" character. This is more or less an "implicit run". Hence, a command line ending on "&" will run the command. If the command generates output, the result depends very much on the console you're using. For CON: and others, the output is mixed with ordinary console output very much like "run" did before. For ViNCEd, the background command is halted as soon as it attempts "to mess the console". Furthermore, the shell prints the shell number of the background command before it is executed, so you know the CLI number. The following shows a typical output generated by this feature: 9.SCSI:> list & [CLI 6] : list 9.SCSI:> "list" suspended. [ViNCEd output] 9.SCSI:> This indicates that we are currently in shell #9 (see the prompt), and "list" is in shell #6 (see the first line below the line with the "&"). List got suspended because its output would otherwise interfere with console output. We may resume "list" by bringing it back into "foreground" by the "fg" script of ViNCEd. Hence: 9.SCSI:> fg 6 Trashcan Dir ----rwed Today 00:09:24 Trashcan.info 1172 ---arw-d 31-Oct-99 20:46:15 .... resumes the listing. This pretty much introduces Un*xoid j ob handling on the Amiga console. To run a command in back- ground, you may use the following syntax: 9.SCSI:> list <>NIL: & [CLI 6] : list 9.SCSI:> which is admittedly not a very useful example, but I guess you got the idea. Added automatic stack size setup for shell commands. This is a new feature that will hopefully limit the number of stack underflows as it allows application developers to increase the stack automatically without the need for stack swap code. The shell scans now the first 1K of each segment of a loaded binary for the magic cookie $STACK: The string behind this cookie should be a decimal number, terminated with a line feed (and an ASCII NUL, i.e. '\0', as for all C strings). This number is then interpreted as the stack size in bytes. The shell will automatically in- crease the stack size *for this command only*. If the pre- defined stack size is larger than the program-implicit, nothing will happen. Example: Add the following new module "stack.c" to your program. Ensure that this module is linked to the beginning of the executable: /** Automatic stack extension cookie follows here. ** this cookie must be placed !at the beginning! or ** at least within the first 1K of data of the code ** or string section. Shell will look for it there ** and will guarantee that the stack size is at least ** as large as specified. **/ char stackcookie[] = "$STACK:10240\n"; /* gimme 10K of stack! */ Old, but leser-known features: Arexx support: If a file has its s-bit and e-bits set and starts with the magic characters "/*", then it is assumed to be a Rexx script and executed thru Arexx. Pipe-Support: If you define either the variable "_pchar" or "_mchar" to a one, or two character sequence, then the shell will forward lines containing these characters to a command named "PIPE" that will handle or rather emulate piping. Various pipe commands can be found on the net. For example, add the following lines to your S:Shell-Startup Set _pchar "|" Set _mchar "||" and install your favourite pipe into "C:". I further recommend to make this pipe command resident. Then the following line will pipe the output of "list" thru "more": 9.SCSI:> list | more ______________________________________________________________________________ Bug fixes: Oh wow, this was a tough job. The Shell really looked like some kind of BCPL left-over. It took several days just to cleanup the code and turn it into something more readable. BCPL was lurking thru the code all over. No more, folks, no more... The V40 shell was unable to perform the "implicit CD" command properly if the directory name was quoted. It inserted an unnecessary blank space behind the directory name. The shell didn't support multiple backticks on the command line; the command line parser was simply broken. Fixed handling of asterisk-backtick sequences. The backtick wasn't escaped properly. The shell did not treat TABs as blank spaces. Fixed. Removed the SetClock cludge. Whoever is still using a 1.3 SetClock nowadays cannot be helped anymore and deserved to be crashed. (-; Added a few missing Forbid/Permit locks around access of the list of resident commands. Removed an ugly hack to set the RC and Result2 variables; this really uses now the proper system functions and doesn't attempt to hack directly into the variable buffers. Reworked the parser a lot; it partially tried to fiddle in the internal buffers of file handles using structures that have never been documented. The code now loads full lines at once (no matter how big they are) and then parses within its buffers. This removes all dependencies of implementation details of the file handles. Arguments to redirection did not expand backticks. Fixed. Added a lot of proper error checking if it is low on memory. The internal (and deceased "GlobalVector") is no longer passed thru to all functions. Instead, I'm now using some SAS magic to allocate my data segment myself on each invocaton. Decided not to disable echo-ing for non-interactive shells. Otherwise, we could not debug scripts or the startup-sequence. Sorry, Heinz, but I reconsidered and it's really better this way.