The following C function implements KEYWORD_DEMO, a system procedure intended to demonstrate how to write the keyword processing code for a routine. It prints the values of its keywords, changes the value of READWRITE to 42 if it is present, and returns. Each line is numbered to make discussion easier. These numbers are not part of the actual program.
Note: The following code is designed to demonstrate keyword processing in a simple, uncluttered example. In actual code, you would not use the printf mechanism used on lines 42-53.
/*1*/ void keyword_demo(int argc, IDL_VPTR *argv, char *argk)
/*2*/ {
/*3*/ typedef struct {
/*4*/ IDL_KW_RESULT_FIRST_FIELD
/*5*/ /* Must be first entry in structure */ IDL_LONG l
/*6*/ float f
/*7*/ double d
/*8*/ int d_there
/*9*/ IDL_STRING s
/*10*/ int s_there
/*11*/ IDL_LONG arr_data[10]
/*12*/ int arr_there
/*13*/ IDL_MEMINT arr_n
/*14*/ IDL_VPTR var
/*15*/ } KW_RESULT
/*16*/ static IDL_KW_ARR_DESC_R arr_d = { IDL_KW_OFFSETOF(arr_data),
/*17*/ 3, 10,IDL_KW_OFFSETOF(arr_n) }
/*18*/
/*19*/ static IDL_KW_PAR kw_pars[] = {
/*20*/ IDL_KW_FAST_SCAN,
/*21*/ { "ARRAY", IDL_TYP_LONG, 1, IDL_KW_ARRAY,
/*22*/ IDL_KW_OFFSETOF(arr_there), CHARA(arr_d) },
/*23*/ { "DOUBLE", IDL_TYP_DOUBLE, 1, 0,
/*24*/ IDL_KW_OFFSETOF(d_there), IDL_KW_OFFSETOF(d) },
/*25*/ { "FLOAT", IDL_TYP_FLOAT, 1, IDL_KW_ZERO, 0,
/*26*/ IDL_KW_OFFSETOF(f) },
/*27*/ { "LONG", IDL_TYP_LONG, 1, IDL_KW_ZERO|IDL_KW_VALUE|15, 0,
/*28*/ IDL_KW_OFFSETOF(l) },
/*29*/ { "READWRITE", IDL_TYP_UNDEF, 1, IDL_KW_OUT|IDL_KW_ZERO,
/*30*/ 0, IDL_KW_OFFSETOF(var) },
/*31*/ { "STRING", TYP_STRING, 1, 0,
/*32*/ IDL_KW_OFFSETOF(s_there), IDL_KW_OFFSETOF(s) },
/*33*/ { NULL }
/*34*/ }
/*35*/
/*36*/ KW_RESULT kw
/*37*/ int i
/*38*/ IDL_ALLTYPES newval
/*39*/
/*40*/ (void) IDL_KWProcessByOffset(argc, argv, argk, kw_pars,
/*41*/ (IDL_VPTR *) 0, 1, &kw)
/*42*/ printf("LONG: <%spresent>\n", kw.l ? "": "not ")
/*43*/ printf("FLOAT: %f\n", kw.f)
/*44*/ printf("DOUBLE: <%spresent>\n", kw.d_there ? "": "not ")
/*45*/ printf("STRING: %s\n",
/*46*/ kw.s_there ? IDL_STRING_STR(&kw.s) : "<not present>")
/*47*/ printf("ARRAY: ")
/*48*/ if (kw.arr_there)
/*49*/ for (i = 0
/*50*/ printf(" %d", kw.arr_data[i])
/*51*/ else
/*52*/ printf("<not present>")
/*53*/ printf("\n")
/*54*/
/*55*/ printf("READWRITE: ")
/*56*/ if (kw.var) {
/*57*/ IDL_Print(1, &kw.var, (char *) 0)
/*58*/ newval.l = 42
/*59*/ IDL_StoreScalar(kw.var, TYP_LONG, &newval)
/*60*/ } else {
/*61*/ printf("<not present>")
/*62*/ }
/*63*/ printf("\n")
/*64*/
/*65*/ IDL_KW_FREE
/*66*/ }
Executing this routine from the IDL command line, by entering:
KEYWORD_DEMO
gives the output:
LONG: <not present>
FLOAT: 0.000000
DOUBLE: <not present>
STRING: <not present>
ARRAY: <not present>
READWRITE: <not present>
Executing it again from the command line with keywords specified:
A = 56
KEYWORD_DEMO, /LONG, FLOAT=2, DOUBLE=34,$
STRING="hello", ARRAY=FINDGEN(10), READWRITE=A
PRINT, 'Final Value of A: ', A
gives the output:
LONG: <present>
FLOAT: 2.000000
DOUBLE: <present>
STRING: hello
ARRAY: 0 1 2 3 4 5 6 7 8 9
READWRITE: 56
Final Value of A: 42
Those features of this procedure that are interesting in terms of keyword processing are, by line number:
3-15: Every system routine that processes keywords must define a KW_RESULT structure type. All output from keyword processing is stored in the fields of this structure.The first field in the KW_RESULT structure must always be IDL_KW_RESULT_FIRST_FIELD. The remaining fields are dictated by the keywords defined in kw_pars below, starting on line 19. The fields with named ending in _there are used for the specified field of the IDL_KW_PAR structs, and must be type int. The types of the other fields must match their definitions in the relevant IDL_KW_PAR and IDL_KW_ARR_DESC_R structs.
16-17: The ARRAY keyword, defined on line 21, is a read-only array, and requires this array description. Note that the data field specifies the location of the arr_data array within KW_RESULT where the array contents should be copied, and the n_offset field specifies the location of the arr_n field where the number of elements actually seen is to be written. Both of these are specified as offsets into KW_RESULT, using the IDL_KW_OFFSET() macro to compute this. The minimum number of elements allowed is 3, the maximum is 10.
19: The start of the keyword definition array. Notice that all of the keywords are ordered lexically (ASCII) and that there is a NULL entry at the end (line 32). Also, all of the mask fields are set to 1, as is the mask argument to IDL_KWProcessByOffset() on line 39. This means that all of the keywords in the list are to be considered valid in this routine.
20: This routine is requesting fast keyword processing. You can learn more about this option in Speeding Keyword Processing.
21-22: ARRAY is a read-only array. Its value field is therefore the actual address (and not an offset into KW_RESULT) of the IDL_KW_ARR_DESC_R struct that completes the array definition. This program wants to know explicitly if ARRAY was specified, so the specified field is set to the offset within KW_RESULT of the arr_there field.
23-24: DOUBLE is a scalar keyword of IDL_TYP_DOUBLE. It uses the variable kw.d_there to know if the keyword is present. Both the specified and value fields are specified as offsets into KW_RESULT.
25: FLOAT is an scalar kIDL_TYP_FLOATeyword. It does not use the specified field of the IDL_KW_PAR struct to get notification of whether the keyword is present, so that field is set to 0. Instead, it uses the IDL_KW_ZERO flag to make sure that the variable kw.f is always zeroed. If the keyword is present, the value will be written into kw.f, otherwise it will remain 0. The important point is that the routine can’t tell the difference between the keyword being absent, or being present with a user- supplied value of zero. If this distinction doesn’t matter, such as when the keyword is to serve as an on/off toggle, use this method. If it does matter, use the specified field as demonstrated with the DOUBLE keyword, above.
27-28: LONG is a scalar keyword of IDL_TYP_LONG. It sets the IDL_KW_ZERO flag to get the variable kw.l zeroed prior to keyword parsing. The use of the IDL_KW_VALUE flag indicates that if the keyword is present, the value 15 (the lower 12 bits of the flags field) will be ORed into the variable kw.l.
29-30: The IDL_KW_OUT flag indicates that the routine wants the IDL_VPTR for READWRITE if it is present. Since IDL_KW_ZERO is also set, the variable kw.var will be zero unless the keyword is present. The specification of IDL_TYP_UNDEF here indicates that there is no type conversion or processing applied to IDL_KW_OUT keywords.
31-32: The STRING keyword demonstrates scalar string keywords.
33: All IDL_KW_PAR arrays must be terminated with a NULL entry.
36: Every system routine that processes keywords must declare a variable named kw, of type KW_RESULT. This variable should be a C stack based local variable (C auto class).
38: The IDL_StoreScalar() function used on line 59 requires the scalar value to be provided in an IDL_ALLTYPES struct.
40-41: Do the keyword processing. The first three arguments are the arguments the interpreter passed to the routine. The plain_args argument is set to NULL because this routine is registered as not accepting any plain arguments. Since no plain arguments will be present, the return value from IDL_KWProcessByOffset() is discarded. The final argument is the address of the KW_RESULT variable (kw) into which the results will be written.
42: The kw.l variable will be 0 if LONG is not present, and 1 if it is.
43: The kw.f variable will always have some usable value, but if it is zero there is no way to know if the keyword was actually specified or not.
45-46: These keywords use the variables from the specified field of their IDL_KW_PAR struct to determine if they were specified or not. Use of the IDL_STRING_STR macro is described in “Accessing IDL_STRING Values".
48-54: Accessing the ARRAY keyword is simple. The kw.arr_there variable indicates if the keyword is present, and kw.arr_n gives the number of elements.
55-63: Since the READWRITE keyword is accessed via the argument’s IDL_VPTR, we use the IDL_Print() function to print its value. This has the same effect as using the user- level PRINT procedure when running IDL. Then, we change its value to 42 using IDL_StoreScalar().
Note: We use this mechanism in order to create a simple example. You will probably want to avoid the use of this type of output (printf and IDL_Print()) in your own code.
65: Normal exit from any routine that calls IDL_KWProcessByOffset() must be preceded by a call to IDL_KW_FREE. This macro releases any dynamic resources that were allocated by keyword processing.