![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Extensions to Cshell This chapter describes the Apex Shell scripting language extensions to cshell. The following topics are covered in this chapter:
- Functions vs. Procedures
- User-Defined Functions
- For Loop
- Object Types
- Editor Operations
- Dialog Operations
Functions vs. ProceduresUnder Apex Shell, commands are either procedures or functions. Procedures are invoked in the same manner as cshell commands, and all standard cshell commands are procedures.
Functions are commands that return a string value. The return value is captured using the command substitution syntax `...`. Procedures and UNIX program calls may also be called with this syntax in order to capture return values.
set x = `basename $in_file` set y = `substring $s 3 5`
This syntax does not allow nested function calls. However, nested function calls can be handled with a set of the nested call to a variable and a variable dereference in its place.
set x = `foo arg1 arg2` echo `bar $x 6`
Calls to user-defined functions where the result is not of interest are written as one-line statements with the function name followed by the actual parameters. However, all other function calls require the `...` syntax.
foo arg1 arg2 arg3
User-Defined FunctionsApex Shell supports user-defined functions with the paired function and end_function keywords.
function name <statements> end_function
Within dialog box script files, keywords begin with the % character:
% function name <statements> % end_function
Within a function, parameters are referenced as $1, $2, etc. However, $argv is not reset within functions. Rather, the new for construct and the built-in functions parameter and parm_count can be used to handle variable argument lists.
function foo for (set i=1; "$i" <= `parm_count`; @ i++) set this=`parameter $i` echo Arg $i is $this end return `parm_count` end_function
The argument to the return statement is the return string for the function. If no return is executed, or no value is given, the function returns the null string.
For LoopApex Shell provides a c-like for statement in the following form:
for (<statement>; <test>; <statement>) ... end
<test> represents a cshell boolean expression. For example:
for (set x = 0; "$x" < "$nlen"; @ x++) names.get element "$x" end
Object TypesWithin cshell, depending on how you look at, there is basically one data type - string. All arguments and results are expressed using strings. Integers and booleans are conceptually present but are implemented as strings. Wordlists are somewhat like flexible arrays of strings.
Apex Shell extends this concept to provide new data types. The new data types facilitate manipulating data and providing direct access to Apex and Summit objects.
Object Declarations
To declare an object of one of these types the statement looks like:
type_name object_name [<arguments
>]
string_set s1 string_map m1 -upper -size 23 string_array a1 input_file f1 /dir/fname view v1 $vname element elt $ssname $eltname $histname task t1 $pathnameFor anyone familiar with C++, it's like a variable declaration with a constructor call with arguments, without the parens, commas, and semicolon.
Some object declarations always require arguments, for example a pathname denoting a view. For others, arguments are not required, for example, declaring a set and taking the default characteristics. There may be declaration options for either kind, for example, a string_map can be created so that the domain values are always uppercased.
The name space of object variables is disjoint from shell variables. Redeclaring an object variable with the same name as an existing one frees any storage associated with the existing one and creates the new one.
Object variables have the same kind of dynamic scope as shell variables. Once they are declared they are visible everywhere. They remain in existence until the script terminates. However, there is also an operation to undeclare an object if one wants to free any space it is using before the script terminates.
For some types, an object can be declared and initialized with the value of another object of that type (like a C++ copy constructor). To do this the name of the other object is given as the single argument in the object declaration, For example,
string_set s2 s1There is support for static variables. An object declaration can be preceded by the word static. Such a declaration is processed only once when it is first executed.
Operation Syntax
Each object type has a set of operations associated with it. These operations are strictly classified as either functions or procedures.
Procedural operation calls are written as one-line statements. Functional operation calls are written using the backquote notation.
To specify the object that an operation is being performed on, we use the traditional dot notation:
object_name.operation_name [<arguments>]
s1.add value m1.bind domain range set line = `f1.get_line` set value = `v1.switch CPP_OPTIONS` set fld = `t1.field Status`
The name before the dot can be the literal name from an object declaration or can be a shell variable or parameter dereference whose string value is the name of an object.
All functional operations return a string value (which may be then processed as an integer or boolean in the usual way if it is one of those).
There are a few operations which construct an object of one of these new types, give it an internally generated name, and return that name as the operation's string value.
This is analogous to a function in a programming language which allocates an object and returns as its value a pointer to that object.
For example, there is an operator on "view" objects which returns a String_Map of the view's switches.
set m1 = `v1.switch_map` set value = `$m1.switch FOO`
Passing the name of an object to a user-defined function is similar, For example, within the function, call operations as:
$1.add value
Type Operations
To see the set of operations available for a type:
type_name.operations
This will print out the names of the functions and procedures specific to that type.
For example, in an xterm you can type
Apex Shell -c string_map.operations
to see the operations specific to the type String_Map. In addition to the operations that are specific to a type there are some operations that are available for all or most types.
The function "name" returns the name or handle of an object if that notion is meaningful for the particular type. If not, the null string is returned:
set pathname = `v1.name` set handle = `elt.name`
The function Type_Name" returns the name of the type of the object.
set tname = `$1.type_name`
The procedure "show" displays an image of the object. For some types this is just the name:
m1.show
Some types support assignment. The statement to assign an object a2 to an object a1 looks like:
a2.assign a1
To delete space and undeclare an object the procedure is called "destroy":
m1.destroy
Required Parameters
Each operation has a required set of parameters.
Given the dynamic nature of operation invocation (for example, $m.$op $a might be a call to string_map.bind with a missing second argument) checks for argument counts and validity are done at run time.
Erroneous parameter counts in object declarations or operation invocations cause the script to terminate at the line on which they occur, just like, No match, etc.
If an operation wants to detect an error but allow the user to deal with it, there is associated with each object a Condition which records the result of the last operation.
The fail and error functions can be used to detect and show error conditions.
view v1 /foo/bar if (`v1.fail`) then echo `v1.error` ... endif
PreprocessingApex Shell supports the c-like preprocessing directives #include, #ifdef, and #define. The values tested in #ifdef must be #defined or environment variables.
Preprocessing must be explicitly enabled by the -P option when invoking apex_shell.
dlisp Insertion
At start-up, the Apex Shell interpreter compiles the script into a tree-structured, internal representation of (abstract) instructions. Each instruction consists of an operation with optional arguments. Each argument may itself be an instruction.
There is another scripting language, dlisp, which gets compiled into this same representation. Instructions in dlisp map one-to-one onto machine instructions.
Apex Shell allows dlisp code to be inserted in Apex Shell scripts. Any one-line statement that starts with < and ends with > is parsed as a dlisp statement.
Editor OperationsWithin menu_item scripts, the substitution variables that are written as <SELECTION>, for example, in the separate-process scripting mechanisms are written within an Apex Shell script as $SELECTION
These values are resolved when the statement containing them is executed. This is in contrast to the separate-process actions where all occurrences of these prompts are presubstituted before the action is run.
An action is specified as being written in Apex Shell by placing the phrase shell apex on the "options" line.
Actions can also be written in dlisp, in which case the "options" line says, shell dlisp.
All of the former action facilities continue to exist.
Apex Shell should only be used for a menu action if the action will finish in a bounded, relatively short time.
Apex and Summit servers are single threaded.
While a server is processing a menu_item Apex Shell action it will not respond to any other events. So, for example, if while testing a new action, it goes into an infinite loop you'll have to kill the server and restart it.
Unlike the separate-process actions, actions written in Apex Shell do not register with the Jobs window.
Within Apex Shell menu_item actions, the statement
perform <operation_name> <arguments>
does the Window_Perform operation on the given window
query <operation_name> <arguments>
does the Window_Query operation on the given window
Dialog OperationsThe dialog specific operations that can be written in Apex Shell are largely the same as the ones described in the dlisp README file in the dialogs subdirectory of product release area ($APEX_HOME/dialogs/README)
You just drop the dlisp brackets, use spaces instead of commas, be careful about unwanted filename expansions, and carefully deal with quote characters, as always with any shell.
Display a line in the output window within a dialog script with the echo statement.
The dialog operations which take a widget as an argument are specially set up to have that parameter implicitly quoted. So you can write
setw name*label foo
without having to put quotes around the first argument.
The .dlisp file parser, by looking at the body of a program or function, decides whether it is written in dlisp or Apex Shell and parses it accordingly. The two formats can be used in the same file.
Limitations
- The cshell :x qualifier is not supported.
- << redirection is not supported.
- File completion is not supported.
Rational Software Corporation http://www.rational.com support@rational.com techpubs@rational.com Copyright © 1993-2001, Rational Software Corporation. All rights reserved. |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |