cslang.tm
来自「一个C格式的脚本处理函数库源代码,可让你的C程序具有执行C格式的脚本文件」· TM 代码 · 共 1,759 行 · 第 1/5 页
TM
1,759 行
the stack. A diagonal array is a 2-d array with all elements zero except for those along the diagonal, which have a value of one:#v+ void make_diagonal_array (int n) { SLang_Array_Type *at; int dims[2]; int i, one; dims[0] = dims[1] = n; at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, dims, 2); if (at == NULL) return; one = 1; for (i = 0; i < n; i++) { dims[0] = dims[1] = i; if (-1 == SLang_set_array_element (at, dims, &one)) { SLang_free_array (at); return; } } (void) SLang_push_array (at, 1); }#v- In this example, only the diagonal elements of the array were set. This is bacause when the array was created, all its elements were set to zero. Now consider an example that acts upon an existing array. In particular, consider one that computes the trace of a 2-d matrix, i.e., the sum of the diagonal elements:#v+ double compute_trace (void) { SLang_Array_Type *at; double trace; int dims[2]; if (-1 == SLang_pop_array_of_type (&at, SLANG_DOUBLE_TYPE)) return 0.0; /* We want a 2-d square matrix. If the matrix is 1-d and has only one element, then return that element. */ trace = 0.0; if (((at->num_dims == 1) && (at->dims[0] == 1)) || ((at->num_dims == 2) && (at->dims[0] == at->dims[1]))) { double dtrace; int n = at->dims[0]; for (i = 0; i < n; i++) { dims[0] = dims[1] = i; (void) SLang_get_array_element (at, &dims, &dtrace); trace += dtrace; } } else SLang_verror (SL_TYPE_MISMATCH, "Expecting a square matrix"); SLang_free_array (at); return trace; } #v- In this example, \cfun{SLang_pop_array_of_type} was used to pop an array of doubles from the stack. This function will make implicit typecasts in order to return an array of the requested type. #%}}}\sect1{Structures} #%{{{ For the purposes of this section, we shall differentiate structures according to whether or not they correspond to an application defined C structure. Those that do are called intrinsic structures, and those do not are called \slang interpreter structures.\sect2{Interpreter Structures} The following simple example shows one method that may be used to create and return a structure with a string and integer field to the interpreter's stack:#v+ int push_struct_example (char *string_value, int int_value) { char *field_names[2]; unsigned char field_types[2]; VOID_STAR field_values[2]; field_names[0] = "string_field"; field_types[0] = SLANG_STRING_TYPE; field_values[0] = &string_value; field_names[1] = "int_field"; field_types[1] = SLANG_INT_TYPE; field_values[1] = &int_value; if (-1 == SLstruct_create_struct (2, field_names, field_types, field_values)) return -1; return 0; }#v- Here, \cfun{SLstruct_create_struct} is used to push a structure with the specified field names and values onto the interpreter's stack. A simpler mechanism exists provided that one has already defined a C structure with a description of how the structure is laid out. For example, consider a C structure defined by#v+ typedef struct { char *s; int i; } SI_Type;#v- Its layout may be specified via a table of \var{SLang_CStruct_Field_Type} entries:#v+ SLang_CStruct_Field_Type SI_Type_Layout [] = { MAKE_CSTRUCT_FIELD(SI_Type, s, "string_field", SLANG_STRING_TYPE, 0), MAKE_CSTRUCT_FIELD(SI_Type, i, "int_field", SLANG_INT_TYPE, 0), SLANG_END_CSTRUCT_TABLE };#v- Here, MAKE_CSTRUCT_FIELD is a macro taking 5 arguments:#v+ MAKE_CSTRUCT_FIELD(C-structure-type, C-field-name, slang-field-name, slang-data-type, is-read-only)#v- The first argument is the structure type, the second is the name of a field of the structure, the third is a string that specifies the name of the corresponding field of the \slang structure, the fourth argument specifies the field's type, and the last argument specifies whether or not the field should be regarded as read-only. Once the layout of the structure has been specified, pushing a \slang version of the structure is trival:#v+ int push_struct_example (char *string_value, int int_value) { SI_Type si; si.s = string_value; si.i = int_value; return SLang_push_cstruct ((VOID_STAR)&si, SI_Type_Layout); }#v- This mechanism of structure creation also permits a \slang structure to be passed to an intrinsic function through the use of the SLang_pop_cstruct routine, e.g.,#v+ void print_si_struct (void) { SI_Type si; if (-1 == SLang_pop_cstruct ((VOID_STAR)&si, SI_Type_Layout)) return; printf ("si.i=%d", si.i); printf ("si.s=%s", si.s); SLang_free_cstruct ((VOID_STAR)&si, SI_Type_Layout); }#v- Assuming \exmp{print_si_struct} exists as an intrinsic function, the \slang code#v+ variable s = struct {string_field, int_field}; s.string_field = "hello"; s.int_field = 20; print_si_struct (s);#v- would result in the display of#v+ si.i=20; si.s=hello#v- Note that the \cfun{SLang_free_cstruct} function was called after the contents of \exmp{si} were nolonger needed. This was necessary because \cfun{SLang_pop_cstruct} allocated memory to set the \exmp{char *s} field of \exmp{si}. Calling \cfun{SLang_free_cstruct} frees up such memory. Now consider the following:#v+ typedef struct { pid_t pid; gid_t group; } X_t;#v- How should the layout of this structure be defined? One might be tempted to use:#v+ SLang_CStruct_Field_Type X_t_Layout [] = { MAKE_CSTRUCT_FIELD(X_t, pid, "pid", SLANG_INT_TYPE, 0), MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_INT_TYPE, 0), SLANG_END_CSTRUCT_TABLE };#v- However, this assumes \exmp{pid_t} and \exmp{gid_t} have been typedefed as ints. But what if \exmp{gid_t} is a \exmp{short}? In such a case, using#v+ MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_SHORT_TYPE, 0),#v- would be the appropriate entry for the \exmp{group} field. Of course, one has no way of knowing how \exmp{gid_t} is declared on other systems. For this reason, it is preferable to use the \var{MAKE_CSTRUCT_INT_FIELD} macro in cases involving integer valued fields, e.g.,#v+ SLang_CStruct_Field_Type X_t_Layout [] = { MAKE_CSTRUCT_INT_FIELD(X_t, pid, "pid", 0), MAKE_CSTRUCT_INT_FIELD(X_t, group, "group", 0), SLANG_END_CSTRUCT_TABLE };#v- Before leaving this section, it is important to mention that access to character array fields is not permitted via this interface. That is, a structure such as#v+ typedef struct { char name[32]; } Name_Type;#v- is not supported since \exmp{char name[32]} is not a \var{SLANG_STRING_TYPE} object. Always keep in mind that a \var{SLANG_STRING_TYPE} object is a \exmp{char *}. \sect2{Intrinsic Structures} Here we show how to make intrinsic structures available to the interpreter. The simplest interface is to structure pointers and not to the actual structures themselves. The latter would require the interpreter to be involved with the creation and destruction of the structures. Dealing with the pointers themselves is far simpler. As an example, consider an object such as#v+ typedef struct _Window_Type { char *title; int row; int col; int width; int height; } Window_Type;#v- which defines a window object with a title, size (\var{width}, \var{height}), and location (\var{row}, \var{col}). We can make variables of type \var{Window_Type} available to the interpreter via a table as follows:#v+ static SLang_IStruct_Field_Type Window_Type_Field_Table [] = { MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 1), MAKE_ISTRUCT_FIELD(Window_Type, row, "row", SLANG_INT_TYPE, 0), MAKE_ISTRUCT_FIELD(Window_Type, col, "col", SLANG_INT_TYPE, 0), MAKE_ISTRUCT_FIELD(Window_Type, width, "width", SLANG_INT_TYPE, 0), MAKE_ISTRUCT_FIELD(Window_Type, height, "height", SLANG_INT_TYPE, 0), SLANG_END_ISTRUCT_TABLE };#v- More precisely, this defines the layout of the \var{Window_Type} structure. Here, the \var{title} has been declared as a read-only field. Using#v+ MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 0),#v- would allow read-write access. Now suppose that \var{My_Window} is a pointer to a \var{Window_Type} object, i.e.,#v+ Window_Type *My_Window;#v- We can make this variable available to the interpreter via the \cfun{SLadd_istruct_table} function:#v+ if (-1 == SLadd_istruct_table (Window_Type_Field_Table, (VOID_STAR) &My_Window, "My_Win")) exit (1);#v- This creates a S-Lang interpreter variable called \var{My_Win} whose value corresponds to the \var{My_Win} structure. This would permit one to access the fields of \var{My_Window} via \slang statements such as#v+ define set_width_and_height (w,h) { My_Win.width = w; My_Win.height = h; }#v- It is extremely important to understand that the interface described in this section does not allow the interpreter to create new instances of \var{Window_Type} objects. The interface merely defines an association or correspondence between an intrinsic structure pointer and a \slang variable. For example, if the value of \var{My_Window} is \var{NULL}, then \var{My_Win} would also be \var{NULL}. One should be careful in allowing read/write access to character string fields. If read/write access is allowed, then the application should always use the \cfun{SLang_create_slstring} and \cfun{SLang_free_slstring} functions to set the character string field of the structure. #%}}}#%}}}#%}}}\chapter{Keyboard Interface} #%{{{#%{{{ Overview \slang's keyboard interface has been designed to allow an application to read keyboard input from the user in a system-independent manner. The interface consists of a set of low routines for reading single character data as well as a higher level interface (\grp{SLkp}) which utilize \slang's keymap facility for reading multi-character sequences. To initialize the interface, one must first call the function \verb{SLang_init_tty}. Before exiting the program, the function \verb{SLang_reset_tty} must be called to restore the keyboard interface to its original state. Once initialized, the low-level \verb{SLang_getkey} function may be used to read \em{simgle} keyboard characters from the terminal. An application using the higher-level \grp{SLkp} interface will read charcters using the \verb{SLkp_getkey} function. In addition to these basic functions, there are also functions to
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?