📄 slstruct.c
字号:
a = (_SLang_Struct_Type **) ap; b = (_SLang_Struct_Type **) bp; for (i = 0; i < na; i++) { b[i] = a[i]; if (a[i] != NULL) a[i]->num_refs += 1; } return 1;}int _SLstruct_define_typedef (void){ char *type_name; _SLang_Struct_Type *s, *s1; SLang_Class_Type *cl; if (-1 == SLang_pop_slstring (&type_name)) return -1; if (-1 == _SLang_pop_struct (&s)) { SLang_free_slstring (type_name); return -1; } if (NULL == (s1 = make_struct_shell (s))) { SLang_free_slstring (type_name); _SLstruct_delete_struct (s); return -1; } _SLstruct_delete_struct (s); if (NULL == (cl = SLclass_allocate_class (type_name))) { SLang_free_slstring (type_name); _SLstruct_delete_struct (s1); return -1; } SLang_free_slstring (type_name); cl->cl_struct_def = s1; cl->cl_init_array_object = struct_init_array_object; cl->cl_datatype_deref = typedefed_struct_datatype_deref; cl->cl_destroy = struct_destroy; cl->cl_push = struct_push; cl->cl_dereference = struct_dereference; cl->cl_foreach_open = struct_foreach_open; cl->cl_foreach_close = struct_foreach_close; cl->cl_foreach = struct_foreach; cl->cl_sget = struct_sget; cl->cl_sput = struct_sput; if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, /* any open slot */ sizeof (_SLang_Struct_Type), SLANG_CLASS_TYPE_PTR)) { /* FIXME: Priority=low */ /* There is a memory leak here if this fails... */ return -1; } /* Note: typecast from a user type to a struct type allowed but not the other * way. */ if (-1 == SLclass_add_typecast (cl->cl_data_type, SLANG_STRUCT_TYPE, struct_typecast, 1)) return -1; return 0;}static intstruct_datatype_deref (unsigned char stype){ (void) stype; if (SLang_peek_at_stack () == SLANG_ARRAY_TYPE) { SLang_Array_Type *at; int status; if (-1 == SLang_pop_array_of_type (&at, SLANG_STRING_TYPE)) return -1; status = SLstruct_create_struct (at->num_elements, (char **) at->data, NULL, NULL); SLang_free_array (at); return status; } SLang_push_integer (SLang_Num_Function_Args); return _SLstruct_define_struct ();}static int register_struct (void){ SLang_Class_Type *cl; if (NULL == (cl = SLclass_allocate_class ("Struct_Type"))) return -1; (void) SLclass_set_destroy_function (cl, struct_destroy); (void) SLclass_set_push_function (cl, struct_push); cl->cl_dereference = struct_dereference; cl->cl_datatype_deref = struct_datatype_deref; cl->cl_foreach_open = struct_foreach_open; cl->cl_foreach_close = struct_foreach_close; cl->cl_foreach = struct_foreach; cl->cl_sget = struct_sget; cl->cl_sput = struct_sput; if (-1 == SLclass_register_class (cl, SLANG_STRUCT_TYPE, sizeof (_SLang_Struct_Type), SLANG_CLASS_TYPE_PTR)) return -1; return 0;}static void get_struct_field_names (_SLang_Struct_Type *s){ SLang_Array_Type *a; char **data; int i, nfields; _SLstruct_Field_Type *f; nfields = (int) s->nfields; if (NULL == (a = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &nfields, 1))) return; f = s->fields; data = (char **) a->data; for (i = 0; i < nfields; i++) { /* Since we are dealing with hashed strings, the next call should not * fail. If it does, the interpreter will handle it at some other * level. */ data [i] = SLang_create_slstring (f[i].name); } SLang_push_array (a, 1);}static int push_struct_fields (_SLang_Struct_Type *s){ _SLstruct_Field_Type *f, *fmax; int num; f = s->fields; fmax = f + s->nfields; num = 0; while (fmax > f) { fmax--; if (-1 == _SLpush_slang_obj (&fmax->obj)) break; num++; } return num;}/* Syntax: set_struct_field (s, name, value); */static void struct_set_field (void){ _SLang_Struct_Type *s; _SLstruct_Field_Type *f; SLang_Object_Type obj; char *name; if (-1 == SLang_pop (&obj)) return; if (-1 == SLang_pop_slstring (&name)) { SLang_free_object (&obj); return; } if (-1 == _SLang_pop_struct (&s)) { SLang_free_slstring (name); SLang_free_object (&obj); return; } if (NULL == (f = pop_field (s, name, find_field))) { _SLstruct_delete_struct (s); SLang_free_slstring (name); SLang_free_object (&obj); return; } SLang_free_object (&f->obj); f->obj = obj; _SLstruct_delete_struct (s); SLang_free_slstring (name);}/* Syntax: set_struct_fields (s, values....); */static void set_struct_fields (void){ unsigned int n; _SLang_Struct_Type *s; _SLstruct_Field_Type *f; n = (unsigned int) SLang_Num_Function_Args; if (-1 == SLreverse_stack (n)) return; n--; if (-1 == _SLang_pop_struct (&s)) { SLdo_pop_n (n); return; } if (n > s->nfields) { SLdo_pop_n (n); SLang_verror (SL_INVALID_PARM, "Too many values for structure"); _SLstruct_delete_struct (s); return; } f = s->fields; while (n > 0) { SLang_Object_Type obj; if (-1 == SLang_pop (&obj)) break; SLang_free_object (&f->obj); f->obj = obj; f++; n--; } _SLstruct_delete_struct (s);}static void get_struct_field (char *name){ (void) struct_sget (0, name);}static int is_struct_type (void){ SLang_Object_Type obj; unsigned char type; int status; if (-1 == SLang_pop (&obj)) return -1; type = obj.data_type; if (type == SLANG_STRUCT_TYPE) status = 1; else status = (NULL != _SLclass_get_class (type)->cl_struct_def); SLang_free_object (&obj); return status;}static SLang_Intrin_Fun_Type Struct_Table [] ={ MAKE_INTRINSIC_1("get_struct_field_names", get_struct_field_names, SLANG_VOID_TYPE, SLANG_STRUCT_TYPE), MAKE_INTRINSIC_1("get_struct_field", get_struct_field, SLANG_VOID_TYPE, SLANG_STRING_TYPE), MAKE_INTRINSIC_1("_push_struct_field_values", push_struct_fields, SLANG_INT_TYPE, SLANG_STRUCT_TYPE), MAKE_INTRINSIC_0("set_struct_field", struct_set_field, SLANG_VOID_TYPE), MAKE_INTRINSIC_0("set_struct_fields", set_struct_fields, SLANG_VOID_TYPE), MAKE_INTRINSIC_0("is_struct_type", is_struct_type, SLANG_INT_TYPE), /* MAKE_INTRINSIC_I("_create_struct", create_struct, SLANG_VOID_TYPE), */ SLANG_END_INTRIN_FUN_TABLE};int _SLstruct_init (void){ if ((-1 == SLadd_intrin_fun_table (Struct_Table, NULL)) || (-1 == register_struct ())) return -1; return 0;}void _SLstruct_pop_args (int *np){ SLang_Array_Type *at; int i, n; _SLang_Struct_Type **data; n = *np; if (n < 0) { SLang_Error = SL_INVALID_PARM; return; } data = (_SLang_Struct_Type **) SLmalloc ((n + 1) * sizeof (_SLang_Struct_Type *)); if (data == NULL) { SLdo_pop_n (n); return; } memset ((char *)data, 0, n * sizeof (_SLang_Struct_Type *)); i = n; while (i > 0) { _SLang_Struct_Type *s; _SLstruct_Field_Type *f; i--; if (NULL == (s = allocate_struct (1))) goto return_error; data[i] = s; s->num_refs += 1; /* keeping a copy */ f = s->fields; if (NULL == (f->name = SLang_create_slstring ("value"))) goto return_error; if (-1 == SLang_pop (&f->obj)) goto return_error; } if (NULL == (at = SLang_create_array (SLANG_STRUCT_TYPE, 0, (VOID_STAR) data, &n, 1))) goto return_error; (void) SLang_push_array (at, 1); return; return_error: for (i = 0; i < n; i++) { _SLang_Struct_Type *s; s = data[i]; if (s != NULL) _SLstruct_delete_struct (s); } SLfree ((char *) data);}void _SLstruct_push_args (SLang_Array_Type *at){ _SLang_Struct_Type **sp; unsigned int num; if (at->data_type != SLANG_STRUCT_TYPE) { SLang_Error = SL_TYPE_MISMATCH; return; } sp = (_SLang_Struct_Type **) at->data; num = at->num_elements; while ((SLang_Error == 0) && (num > 0)) { _SLang_Struct_Type *s; num--; if (NULL == (s = *sp++)) { SLang_push_null (); continue; } /* I should check to see if the value field is present, but... */ (void) _SLpush_slang_obj (&s->fields->obj); }}/* C structures */static _SLstruct_Field_Type *find_field_via_strcmp (_SLang_Struct_Type *s, char *name){ _SLstruct_Field_Type *f, *fmax; f = s->fields; fmax = f + s->nfields; while (f < fmax) { if (0 == strcmp (name, f->name)) return f; f++; } return NULL;}static void free_cstruct_field (SLang_CStruct_Field_Type *cfield, VOID_STAR cs){ SLang_Class_Type *cl; if ((cfield->read_only == 0) && (NULL != (cl = _SLclass_get_class (cfield->type)))) _SLarray_free_array_elements (cl, (VOID_STAR)((char*)cs + cfield->offset), 1);}void SLang_free_cstruct (VOID_STAR cs, SLang_CStruct_Field_Type *cfields){ if ((cs == NULL) || (cfields == NULL)) return; while (cfields->field_name != NULL) { free_cstruct_field (cfields, cs); cfields++; }}int SLang_pop_cstruct (VOID_STAR cs, SLang_CStruct_Field_Type *cfields){ _SLang_Struct_Type *s; SLang_CStruct_Field_Type *cfield; char *field_name; char *cs_addr; if ((cfields == NULL) || (cs == NULL)) return -1; if (-1 == _SLang_pop_struct (&s)) return -1; cfield = cfields; cs_addr = (char *) cs; while (NULL != (field_name = cfield->field_name)) { _SLstruct_Field_Type *f; SLang_Class_Type *cl; if ((cfield->read_only == 0) && ((NULL == (f = pop_field (s, field_name, find_field_via_strcmp))) || (-1 == _SLpush_slang_obj (&f->obj)) || (NULL == (cl = _SLclass_get_class (cfield->type))) || (-1 == (*cl->cl_apop)(cfield->type, (VOID_STAR) (cs_addr + cfield->offset))))) goto return_error; cfield++; } _SLstruct_delete_struct (s); return 0; return_error: while (cfield != cfields) { free_cstruct_field (cfield, cs); cfield--; } _SLstruct_delete_struct (s); return -1;}static _SLang_Struct_Type *create_cstruct (VOID_STAR cs, SLang_CStruct_Field_Type *cfields){ unsigned int i, n; _SLang_Struct_Type *s; SLang_CStruct_Field_Type *cfield; char **field_names; VOID_STAR *field_values; SLtype *field_types; if ((cs == NULL) || (cfields == NULL)) return NULL; cfield = cfields; while (cfield->field_name != NULL) cfield++; n = cfield - cfields; if (n == 0) { SLang_verror (SL_APPLICATION_ERROR, "C structure has no fields"); return NULL; } s = NULL; field_types = NULL; field_values = NULL; if ((NULL == (field_names = (char **) SLmalloc (n*sizeof (char *)))) || (NULL == (field_types = (SLtype *)SLmalloc (n*sizeof(SLtype)))) || (NULL == (field_values = (VOID_STAR *)SLmalloc (n*sizeof(VOID_STAR))))) goto return_error; for (i = 0; i < n; i++) { cfield = cfields + i; field_names[i] = cfield->field_name; field_types[i] = cfield->type; field_values[i] = (VOID_STAR)((char *)cs + cfield->offset); } s = create_struct (n, field_names, field_types, field_values); /* drop */ return_error: SLfree ((char *) field_values); SLfree ((char *) field_types); SLfree ((char *) field_names); return s;} int SLang_push_cstruct (VOID_STAR cs, SLang_CStruct_Field_Type *cfields){ _SLang_Struct_Type *s; if (NULL == (s = create_cstruct (cs, cfields))) return -1; if (0 == _SLang_push_struct (s)) return 0; _SLstruct_delete_struct (s); return -1;}int SLang_assign_cstruct_to_ref (SLang_Ref_Type *ref, VOID_STAR cs, SLang_CStruct_Field_Type *cfields){ _SLang_Struct_Type *s; if (NULL == (s = create_cstruct (cs, cfields))) return -1; if (0 == SLang_assign_to_ref (ref, SLANG_STRUCT_TYPE, (VOID_STAR) &s)) return 0; _SLstruct_delete_struct (s); return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -