Temporary Variables
As discussed previously, IDL maintains a pool of nameless variables known as temporary variables. These variables are used by the interpreter to hold temporary results from evaluating expressions, and are also used within system procedures and functions that need temporary workspace. In addition, system functions often obtain a temporary variable to return the result of their operation to the interpreter. Temporary variables have the following characteristics:
- All temporaries, when initially allocated, are of type IDL_TYP_UNDEF.
- Temporary variables do not have a name associated with them.
- Routines that check out temporaries must either check them back in or return them as the result of the function. Once you return a temporary variable, you cannot access it again.
- Temporary variables are reclaimed by the interpreter when it is about to exit after executing a program, so it is not possible to lose them and leak dynamic memory by allocating them and failing to return them. If the interpreter is exiting normally and it detects temporaries that have not been returned, it issues an error message. Such an error message indicates an error in the implementation of your system routine. If your routine exits by issuing an IDL_MSG_LONGJMP or IDL_MSG_IO_LONGJMP error via IDL_Message() however, allocated temporaries are expected, and are reclaimed quietly. Hence, your routines need only return temporaries on normal return, and not before issuing errors. See IDL Internals: Error Handling.
The interpreter uses temporary variables to hold values that are the result of evaluating expressions. Such temporaries are pushed on the interpreter stack where they are often passed as arguments to other routines. For example, the IDL statement:
PRINT, MAX(FINDGEN(100))
Causes the interpreter to perform the following steps:
- Push a constant variable with the value 100 onto the stack.
- Call the system function FINDGEN, passing it one argument.
- FINDGEN returns a temporary variable which is a 100-element vector with each element set to the value of its index.
- The interpreter removes the arguments to FINDGEN from the stack (the constant 100) and pushes the resulting temporary variable onto the stack.
- The MAX system function is called with a single argument—the temporary result from FINDGEN.
- MAX finds the largest element in its argument (99), places that value into a temporary scalar variable, and returns that temporary variable as its result.
- The interpreter removes the argument to MAX from the stack. This was the temporary array from FINDGEN, so it is returned to the pool of temporary variables. The resulting temporary variable from MAX is then pushed onto the stack.
- The PRINT system procedure is called with a single argument, which is the temporary scalar variable from MAX. It prints the value of the variable and returns.
- The interpreter removes the argument to PRINT from the stack, and returns it to the pool of temporary variables.
Getting a Temporary Variable
Temporary variables are obtained via the IDL_Gettmp() function:
IDL_VPTR IDL_Gettmp(void);
IDL_Gettmp() requires no arguments, and returns an IDL_VPTR to a temporary variable. This variable must be returned to the pool of temporary variables (with a call to IDL_Deltmp()) or be returned as the value of a system function before control returns to the interpreter, or an error will occur.
A number of variants on IDL_Gettmp() exist, as convenience routines for creating temporary scalar variables of a given type and value. In all cases, the value is supplied as the sole argument, and the resulting type is indicated by the name of the routine:
IDL_VPTR IDL_GettmpInt(IDL_INT value);
IDL_VPTR IDL_GettmpUInt(IDL_UINT value);
IDL_VPTR IDL_GettmpLong(IDL_LONG value);
IDL_VPTR IDL_GettmpULong(IDL_ULONG value);
IDL_VPTR IDL_GettmpFILEINT(IDL_FILEINT value);
IDL_VPTR IDL_GettmpMEMINT(IDL_MEMINT value);
Creating a Temporary Array
Temporary array variables can be obtained via the IDL_MakeTempArray() function:
char *IDL_MakeTempArray(int type, int n_dim, IDL_MEMINT dim[],
int init, IDL_VPTR *var)
where:
type
The type code for the resulting array. See Type Codes.
n_dim
The number of array dimensions. The constant IDL_MAX_ARRAY_DIM defines the upper limit of this value.
dim
An array of IDL_MAX_ARRAY_DIM elements containing the array dimensions. The number of dimensions in the array is given by the n_dim argument.
init
Specifies the sort of initialization that should be applied to the resulting array. The
init argument must be one of the following:
- IDL_ARR_INI_INDEX: Each element of the array is set to the value of its index. The INDGEN family of built-in system functions is implemented using this feature.
- IDL_ARR_INI_NOP: No initialization is done. The data area of the array will contain whatever garbage was left behind from its previous use. Experience has shown that IDL_TYP_STRING data should never be left uninitialized due to the risk of dereferencing an invalid string pointer and crashing IDL. Therefore, IDL_TYP_STRING data is zeroed when IDL_ARR_INI_NOP is specified.
- IDL_ARR_INI_ZERO: The data area of the array is zeroed.
var
The address of an IDL_VPTR where the address of the resulting temporary variable will be put.
The data area of an array IDL_VARIABLE is accessible from its IDL_VPTR as var->value.arr->data. However, since most routines that create an array need to access the data area, IDL_MakeTempArray() returns the data area pointer as its value. As with IDL_Gettmp(), the variable allocated via IDL_MakeTempArray() must be returned to the pool of temporary variables or be returned as the value of a system function before control returns to the interpreter, or an error will occur.
Creating a Temporary Vector
IDL_MakeTempArray() can be used to create arrays with any number of dimensions, but the common case of creating a 1-dimensional vector can be carried out more conveniently using the IDL_MakeTempVector() function:
char *IDL_MakeTempVector(int type, IDL_MEMINT dim, int init, IDL_VPTR *var)where:
type, init, var
These arguments are the same as for IDL_MakeTempArray().
dim
The number of elements in the resulting vector.
Creating a Temporary Structure
The IDL_MakeTempStruct() allows you to create an IDL structure variable using memory allocated by IDL, in much the same way that IDL_MakeStruct() and IDL_ImportArray() allow you to create an IDL structure variable using memory you provide. Temporary structure variables can be obtained via the IDL_MakeTempStruct() function:
char *IDL_MakeTempStruct(IDL_StructDefPtr sdef, int n_dim,
IDL_MEMINT dim[], IDL_VPTR *var, int zero)
where:
sdef
A pointer to the structure definition.
n_dim
The number of structure dimensions. The constant IDL_MAX_ARRAY_DIM defines the upper limit of this value.
dim
A C array of IDL_MAX_ARRAY_DIM elements containing the structure dimensions. The number of dimensions in the array is given by the n_dim argument.
var
The address of an IDL_VPTR where the address of the resulting temporary variable will be put.
The data area of an array IDL_VARIABLE is accessible from its IDL_VPTR as var->value.arr->data. However, since most routines that create an array need to access the data area, IDL_MakeTempStruct() returns the data area pointer as its value. As with IDL_Gettmp(), the variable allocated via IDL_MakeTempStruct() must be returned to the pool of temporary variables (with a call to IDL_Deltmp()) or be returned as the value of a system function before control returns to the interpreter, or an error will occur.
zero
Set to TRUE if the data area of the resulting variable should be zeroed, or to FALSE otherwise. Unless the caller intends to immediately copy a valid result into the variable, this argument should be set to TRUE to prevent memory corruption.
Creating a Temporary Vector
IDL_MakeTempStruct() can be used to create arrays with any number of dimensions, but the common case of creating a 1-dimensional vector can be carried out more conveniently using the IDL_MakeTempStructVector() function:
char *IDL_MakeTempStructVector(IDL_StructDefPtr sdef, IDL_MEMINT
dim, IDL_VPTR *var, int zero)
where:
sdef, var, zero
These arguments are the same as for IDL_MakeTempStruct().
dim
The number of elements in the resulting vector.
Creating A Temporary Variable Using Another Variable As A Template
It is common to want to create a temporary variable with a form that mimics that of a variable you already have access to. Often, such a temporary variable has the same number of elements and dimensions, but may vary in type. It is possible to do this by using the basic temporary variable creation routines discussed earlier in this section, but the resulting code will be complex, and this sort of code occurs frequently. The best way to create such a variable is using the IDL_VarMakeTempFromTemplate() function.
IDL_VarMakeTempFromTemplate() creates a temporary variable of the desired type, using the template_var argument to specify its dimensionality. The address of this temporary variable is stored at the address specified by the result_addr argument. The address of the start of this variable’s data area is returned as the value of the function.
char *IDL_VarMakeTempFromTemplate(IDL_VPTR template_var,int type,
IDL_StructDefPtr sdef, IDL_VPTR *result_addr,int zero);
where:
template_var
Source variable to take dimensionality from. This can be a scalar or array of any type.
type
The IDL type code for the desired temporary variable.
sdef
NULL, or a pointer to a structure definition. This argument is ignored if type is not IDL_TYP_STRUCT. If type is IDL_TYP_STRUCT, sdef supplies the structure definition for the result. It is an error to specify a result type of IDL_TYP_STRUCT without providing a value for sdef, with one exception: If type is IDL_TYP_STRUCT and template_var is a variable of IDL_TYP_STRUCT, and sdef is NULL, then IDL_VarMakeTempFromTemplate() will use structure definition of template_var.
result_addr
Address of IDL_VPTR to receive a pointer to the newly allocated temporary variable.
zero
TRUE if the resulting variable should be zeroed, and FALSE to not do this. Variables of IDL_TYP_STRING, and structure types that contain strings, are always zeroed.
Freeing A Temporary Variable
Use IDL_Deltmp() to free a temporary variable:
void IDL_Deltmp(IDL_VPTR p)
where p is an IDL_VPTR to the temporary variable to be returned. IDL_Deltmp() frees the dynamic parts of the temporary variable (if any) and then returns the variable to the pool of available temporaries. Once you have deallocated a temporary variable, you may not access it again. There is also a macro named IDL_DELTMP which checks its argument to make sure it’s a temporary, and if so, calls IDL_Deltmp() to return it.