Additional Topics > External Development Guide > Obsolete Internal Interfaces > Simplified Routine Invocation

# Simplified Routine Invocation

The functions and techniques described in this section are no longer widely used, and are considered functionally obsolete although they continue to be supported by Exelis VIS. This section is supplied to help those maintaining older code. New code should be written using the information found in Adding System Routines.

A great deal of the work involved in writing IDL system routines involves checking positional arguments, screening out illegal combinations of type and structure, and converting them to desired type. The function IDL_EzCall() provides a simplified way to handle this task. It processes an array of IDL_EZ_ARG structs which describe the processing to be applied to each positional argument.

The IDL_EzCall() function is similar to the facility provided for keyword arguments by IDL_KWGetParams():

void IDL_EzCall(int argc, IDL_VPTR argv[], IDL_EZ_ARG arg_struct[]);

where:

### argc

The number of positional arguments present.

### argv

An array of pointers to the positional arguments.

### arg_struct

An array of IDL_EZ_ARG structures defining the desired characteristics for each possible argument. Note that this array must have a definition for every possible parameter whether that argument is present in the current call or not. The order of the IDL_EZ_ARG structures is the same as the order in which the arguments are specified in the call. (See “The IDL_EZ_ARG struct” on page 405.)

There are some things you need to be aware of when using IDL_EzCall():

- IDL_EzCall() automatically excludes file variables (such as those created by the ASSOC function) so you don’t have to take any special action to screen such variables out.
- Every call to IDL_EzCall() must have a matching call to IDL_EzCallCleanup() before execution returns to the interpreter.
- IDL_EzCall() does not handle keyword arguments. If the calling routine allows keyword arguments, it must do its own keyword processing using IDL_KWGetParams() (see “IDL Internals: Keyword Processing” on page 121) and pass an argv containing only positional arguments to IDL_EzCall().
- If you mark a variable as being write-only, you shouldn’t count on anything useful being in the uargv or value fields. This implies that it is not a good idea to set the IDL_EZ_POST_WRITEBACK field in the post field. Instead, you will have to allocate a new temporary variable, place the desired value into it, and use the IDL_VarCopy() function to write its value back into the original argv entry yourself.

IDL_EZ_POST_WRITEBACK is only useful when the access field is set to IDL_EZ_ACCESS_RW.

## The IDL_EZ_ARG struct

The IDL_EZ_ARG struct has the following definition:

typedef struct {

short allowed_dims; short allowed_types; short access;

short convert; short pre; short post;

IDL_VPTR to_delete; IDL_VPTR uargv; IDL_ALLTYPES value;

} IDL_EZ_ARG;

where:

### allowed_dims

A bit mask that specifies the allowed dimensions. Bit 0 means scalar, bit 1 means one-dimensional, etc. The IDL_EZ_DIM_MASK macro can be used to specify certain bits. It accepts a single argument that specifies the number of dimensions that are accepted, and returns the bit value that represents that number. For example, to specify that the argument can be scalar or have 2 dimensions:

IDL_EZ_DIM_MASK(0) | IDL_EZ_DIM_MASK(2)

In addition, the following constants are defined to simplify the writing of common cases:

IDL_EZ_DIM_ARRAY

Allow all but scalar.

IDL_EZ_DIM_ANY

Allow anything.

### allowed_types

This is a bit mask defining the allowed data types for the argument. To convert type codes to the appropriate bits, use the formula BitMask = 2TypeCode or use the IDL_TYP_MASK macro.

If you specify a value for the convert field, its a good idea to specify IDL_TYP_B_ALL or IDL_TYP_B_SIMPLE here. The type conversion will catch any problems and your routine will be more flexible.

### access

A bitmask that describes the type of access to be allowed to the argument. The following constants should be OR’d together to set the proper value:

IDL_EZ_ACCESS_R

The value of the argument is used by the system routine.

IDL_EZ_ACCESS_W

The value of the argument is changed by the system routine. This means that it must be a named variable (as opposed to a constant or expression).

IDL_EZ_ACCESS_RW

This is equivalent to IDL_EZ_ACCESS_R | IDL_EZ_ACCESS_W.

### convert

The type code for the type to which the argument will be converted. A value of

IDL_TYP_UNDEF means that no conversion will be applied.

### pre

A bitmask that specifies special purpose processing that should be performed on the variable by IDL_EzCall(). These bits are specified with the following constants:

IDL_EZ_PRE_SQMATRIX

The argument must be a square matrix.

IDL_EZ_PRE_TRANSPOSE

Transpose the argument.

This processing occurs after any type conversions specified by convert, and is only done if the access field has the IDL_EZ_ACCESS_R bit set.

### post

A bit mask that specifies special purpose processing that should be performed on the variable by IDL_EzCallCleanup(). These bits are specified with the following constants:

IDL_EZ_POST_WRITEBACK

Transfer the contents of the uargv field back to the actual argument.

IDL_EZ_POST_TRANSPOSE

Transpose uargv prior to transferring its contents back to the actual argument. This processing occurs only when the access field has the IDL_EZ_ACCESS_W bit set. If IDL_EZ_POST_WRITEBACK is not present, none of the other actions are considered, since that would imply wasted effort.

### to_delete

Do not make use of this field. This field is reserved for use by the EZ module. If IDL_EzCall() allocated a temporary variable to satisfy the conversion requirements given by the convert field, the IDL_VPTR to that temporary is saved here for use by IDL_EzCallCleanup().

### uargv

After calling IDL_EzCall(), uargv contains a pointer to the IDL_VARIABLE which is the argument. This is the IDL_VPTR that your routine should use. Depending on the required type conversions, it might be the actual argument, or a temporary variable containing a converted version of the original. This field won’t contain anything useful if the IDL_EZ_ACCESS_R bit is not set in the access field.

### value

This is a copy of the value field of the IDL_VARIABLE pointed at by uargv. For scalar variables, it contains the value, for arrays it points at the array block. This field is here to make reading read-only variables faster. Note that this is only a copy from uargv, and changing it will not cause the actual value field in uargv to be updated.

## Cleaning Up

Every call to IDL_EzCall() must be bracketed by a call to IDL_EzCallCleanup():

void IDL_EzCallCleanup(int argc, IDL_VPTR argv[], IDL_EZ_ARG arg_struct[]);

The arguments are exactly the same as those passed to IDL_EzCall().

### Example— using IDL_EzCall()

The following function skeleton shows how to use the simplified interface to handle argument processing for an older version of the built-in SVD (Singular Value Decomposition) function. SVD accepts the following positional arguments (in order):

#### A

An m by n matrix (input, required).

#### w

An n-element vector (output, required).

#### U

An n by m matrix (output, optional)

#### V

An n by n matrix (output, optional)

void nr_svdcmp(int argc, IDL_VPTR argv[])

{

.

.

.

static IDL_EZ_ARG arg_struct[] = {

{ IDL_EZ_DIM_MASK(2), IDL_TYP_B_SIMPLE, IDL_EZ_ACCESS_R, IDL_TYP_FLOAT, 0, 0 }, /* A */

{ IDL_EZ_DIM_ANY, IDL_TYP_B_ALL,

IDL_EZ_ACCESS_W, 0, 0, 0 }, /* w */

{ IDL_EZ_DIM_ANY, IDL_TYP_B_ALL, IDL_EZ_ACCESS_W, 0, 0, 0 }, /* U */

{ IDL_EZ_DIM_ANY, IDL_TYP_B_ALL, IDL_EZ_ACCESS_W, 0, 0, 0 } /* V */

};

IDL_EzCall(argc, argv, arg_struct);

.

.

.

/* Do the SVD calculation and prepare temporary variables to be returned as w, U, and V */

.

.

.

IDL_EzCallCleanup(argc, argv, arg_struct);

}

Those features of this procedure that are interesting in terms of plain argument processing are, by line number:

7-8 - The settings of the various fields of the IDL_EZ_ARG struct for the first positional argument (A) specifies:

- allowed_dims. The argument must be 2-dimensional.
- allowed_types. It can have any simple type. Types and type codes are discussed in “IDL Internals: Types”.
- access The routine will examine the argument’s value, but will not attempt to change it.
- convert The argument should be converted to IDL_TYP_FLOAT if necessary.
- pre No pre-processing is required.
- post No post-processing is required.

The remaining fields are all set by IDL_EzCall() in response to the above.

9-14 - Arguments two through four are allowed to have any number of dimensions and are allowed any type. This is because the routine does not intend to examine them, only to change them. For the same reason, a zero (IDL_TYP_UNDEF) is specified for the convert field indicating that no type conversion is desired. No pre or post-processing is specified.

17 - Process the positional arguments.

26 - Clean up.