📄 slstruct.c
字号:
/* Structure type implementation *//* Copyright (c) 1998, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"/* #define SL_APP_WANTS_FOREACH */#include "slang.h"#include "_slang.h"void _SLstruct_delete_struct (_SLang_Struct_Type *s){ _SLstruct_Field_Type *field, *field_max; if (s == NULL) return; if (s->num_refs > 1) { s->num_refs -= 1; return; } field = s->fields; if (field != NULL) { field_max = field + s->nfields; while (field < field_max) { SLang_free_object (&field->obj); SLang_free_slstring (field->name); /* could be NULL */ field++; } SLfree ((char *) s->fields); } SLfree ((char *) s);}static _SLang_Struct_Type *allocate_struct (unsigned int nfields){ _SLang_Struct_Type *s; _SLstruct_Field_Type *f; unsigned int i, size; s = (_SLang_Struct_Type *) SLmalloc (sizeof (_SLang_Struct_Type)); if (s == NULL) return NULL; SLMEMSET((char *) s, 0, sizeof (_SLang_Struct_Type)); size = nfields * sizeof(_SLstruct_Field_Type); if (NULL == (f = (_SLstruct_Field_Type *) SLmalloc (size))) { SLfree ((char *) s); return NULL; } SLMEMSET ((char *) f, 0, size); s->nfields = nfields; s->fields = f; /* By default, all structs will be created with elements set to NULL. I * do not know whether or not it is better to use SLANG_UNDEFINED_TYPE. */ for (i = 0; i < nfields; i++) f[i].obj.data_type = SLANG_NULL_TYPE; return s;}static int push_struct_of_type (unsigned char type, _SLang_Struct_Type *s){ SLang_Object_Type obj; obj.data_type = type; obj.v.struct_val = s; s->num_refs += 1; if (0 == SLang_push (&obj)) return 0; s->num_refs -= 1; return -1;}int _SLang_push_struct (_SLang_Struct_Type *s){ return push_struct_of_type (SLANG_STRUCT_TYPE, s);}int _SLang_pop_struct (_SLang_Struct_Type **sp){ SLang_Object_Type obj; SLang_Class_Type *cl; unsigned char type; if (0 != SLang_pop (&obj)) return -1; type = obj.data_type; if (type != SLANG_STRUCT_TYPE) { cl = _SLclass_get_class (type); if (cl->cl_struct_def == NULL) { *sp = NULL; SLang_free_object (&obj); SLang_verror (SL_TYPE_MISMATCH, "Expecting struct type object. Found %s", cl->cl_name); return -1; } } *sp = obj.v.struct_val; return 0;}static void struct_destroy (unsigned char type, VOID_STAR vs){ (void) type; _SLstruct_delete_struct (*(_SLang_Struct_Type **) vs);}static int struct_push (unsigned char type, VOID_STAR ptr){ return push_struct_of_type (type, *(_SLang_Struct_Type **) ptr);}static _SLstruct_Field_Type *find_field (_SLang_Struct_Type *s, char *name){ _SLstruct_Field_Type *f, *fmax; f = s->fields; fmax = f + s->nfields; while (f < fmax) { /* Since both these are slstrings, only compare pointer */ if (name == f->name) return f; f++; } return NULL;}static _SLstruct_Field_Type *pop_field (_SLang_Struct_Type *s, char *name, _SLstruct_Field_Type *(*find)(_SLang_Struct_Type *, char *)){ _SLstruct_Field_Type *f; f = (*find) (s, name); if (f == NULL) SLang_verror (SL_INVALID_PARM, "struct has no field named %s", name); return f;}static _SLang_Struct_Type * create_struct (unsigned int nfields, char **field_names, unsigned char *field_types, VOID_STAR *field_values){ _SLang_Struct_Type *s; _SLstruct_Field_Type *f; unsigned int i; if (NULL == (s = allocate_struct (nfields))) return NULL; f = s->fields; for (i = 0; i < nfields; i++) { unsigned char type; SLang_Class_Type *cl; VOID_STAR value; char *name = field_names [i]; if (name == NULL) { SLang_verror (SL_APPLICATION_ERROR, "A struct field name cannot be NULL"); goto return_error; } if (-1 == _SLcheck_identifier_syntax (name)) goto return_error; if (NULL == (f->name = SLang_create_slstring (name))) goto return_error; if ((field_values == NULL) || (NULL == (value = field_values [i]))) { f++; continue; } type = field_types[i]; cl = _SLclass_get_class (type); if ((-1 == (cl->cl_apush (type, value))) || (-1 == SLang_pop (&f->obj))) goto return_error; f++; } return s; return_error: _SLstruct_delete_struct (s); return NULL;}int SLstruct_create_struct (unsigned int nfields, char **field_names, unsigned char *field_types, VOID_STAR *field_values){ _SLang_Struct_Type *s; if (NULL == (s = create_struct (nfields, field_names, field_types, field_values))) return -1; if (0 == _SLang_push_struct (s)) return 0; _SLstruct_delete_struct (s); return -1;}/* Interpreter interface */int _SLstruct_define_struct (void){ int nfields; _SLang_Struct_Type *s; _SLstruct_Field_Type *f; if (-1 == SLang_pop_integer (&nfields)) return -1; if (nfields <= 0) { SLang_verror (SL_INVALID_PARM, "Number of struct fields must be > 0"); return -1; } if (NULL == (s = allocate_struct (nfields))) return -1; f = s->fields; while (nfields) { char *name; nfields--; if (-1 == SLang_pop_slstring (&name)) { _SLstruct_delete_struct (s); return -1; } f[nfields].name = name; } if (-1 == _SLang_push_struct (s)) { _SLstruct_delete_struct (s); return -1; } return 0;}/* Simply make a struct that contains the same fields as struct s. Do not * duplicate the field values. */static _SLang_Struct_Type *make_struct_shell (_SLang_Struct_Type *s){ _SLang_Struct_Type *new_s; _SLstruct_Field_Type *new_f, *old_f; unsigned int i, nfields; nfields = s->nfields; if (NULL == (new_s = allocate_struct (nfields))) return NULL; new_f = new_s->fields; old_f = s->fields; for (i = 0; i < nfields; i++) { if (NULL == (new_f[i].name = SLang_create_slstring (old_f[i].name))) { _SLstruct_delete_struct (new_s); return NULL; } } return new_s;}static int struct_init_array_object (unsigned char type, VOID_STAR addr){ SLang_Class_Type *cl; _SLang_Struct_Type *s; cl = _SLclass_get_class (type); if (NULL == (s = make_struct_shell (cl->cl_struct_def))) return -1; s->num_refs = 1; *(_SLang_Struct_Type **) addr = s; return 0;}static inttypedefed_struct_datatype_deref (unsigned char type){ SLang_Class_Type *cl; _SLang_Struct_Type *s; cl = _SLclass_get_class (type); if (NULL == (s = make_struct_shell (cl->cl_struct_def))) return -1; if (-1 == push_struct_of_type (type, s)) { _SLstruct_delete_struct (s); return -1; } return 0;}static _SLang_Struct_Type *duplicate_struct (_SLang_Struct_Type *s){ _SLang_Struct_Type *new_s; _SLstruct_Field_Type *new_f, *f, *fmax; new_s = make_struct_shell (s); if (new_s == NULL) return NULL; f = s->fields; fmax = f + s->nfields; new_f = new_s->fields; while (f < fmax) { SLang_Object_Type *obj; obj = &f->obj; if (obj->data_type != SLANG_UNDEFINED_TYPE) { if ((-1 == _SLpush_slang_obj (obj)) || (-1 == SLang_pop (&new_f->obj))) { _SLstruct_delete_struct (new_s); return NULL; } } new_f++; f++; } return new_s;}static int struct_dereference (unsigned char type, VOID_STAR addr){ _SLang_Struct_Type *s; if (NULL == (s = duplicate_struct (*(_SLang_Struct_Type **) addr))) return -1; if (-1 == push_struct_of_type (type, s)) { _SLstruct_delete_struct (s); return -1; } return 0;}/*{{{ foreach */struct _SLang_Foreach_Context_Type{ _SLang_Struct_Type *s; char *next_field_name;};static SLang_Foreach_Context_Type *struct_foreach_open (unsigned char type, unsigned int num){ SLang_Foreach_Context_Type *c; _SLang_Struct_Type *s; char *next_name; (void) type; if (-1 == _SLang_pop_struct (&s)) return NULL; switch (num) { case 0: next_name = SLang_create_slstring ("next"); break; case 1: if (-1 == SLang_pop_slstring (&next_name)) next_name = NULL; break; default: next_name = NULL; SLang_verror (SL_NOT_IMPLEMENTED, "'foreach (Struct_Type) using' requires single control value"); SLdo_pop_n (num); break; } if (next_name == NULL) { _SLstruct_delete_struct (s); return NULL; } c = (SLang_Foreach_Context_Type *)SLmalloc (sizeof (SLang_Foreach_Context_Type)); if (c == NULL) { _SLstruct_delete_struct (s); SLang_free_slstring (next_name); return NULL; } memset ((char *) c, 0, sizeof (SLang_Foreach_Context_Type)); c->next_field_name = next_name; c->s = s; return c;}static void struct_foreach_close (unsigned char type, SLang_Foreach_Context_Type *c){ (void) type; if (c == NULL) return; SLang_free_slstring (c->next_field_name); if (c->s != NULL) _SLstruct_delete_struct (c->s); SLfree ((char *) c);}static int struct_foreach (unsigned char type, SLang_Foreach_Context_Type *c){ _SLstruct_Field_Type *f; _SLang_Struct_Type *next_s; (void) type; if (c == NULL) return -1; if (c->s == NULL) return 0; /* done */ if (-1 == _SLang_push_struct (c->s)) return -1; /* Now get the next one ready for the next foreach loop */ next_s = NULL; if (NULL != (f = find_field (c->s, c->next_field_name))) { SLang_Class_Type *cl; cl = _SLclass_get_class (f->obj.data_type); /* Note that I cannot simply look for SLANG_STRUCT_TYPE since the * user may have typedefed another struct type. So, look at the * class methods. */ if (cl->cl_foreach_open == struct_foreach_open) { next_s = f->obj.v.struct_val; next_s->num_refs += 1; } } _SLstruct_delete_struct (c->s); c->s = next_s; /* keep going */ return 1;}/*}}}*/static int struct_sput (unsigned char type, char *name){ _SLang_Struct_Type *s; _SLstruct_Field_Type *f; SLang_Object_Type obj; (void) type; if (-1 == _SLang_pop_struct (&s)) return -1; if ((NULL == (f = pop_field (s, name, find_field))) || (-1 == SLang_pop (&obj))) { _SLstruct_delete_struct (s); return -1; } SLang_free_object (&f->obj); f->obj = obj; _SLstruct_delete_struct (s); return 0;}static int struct_sget (unsigned char type, char *name){ _SLang_Struct_Type *s; _SLstruct_Field_Type *f; int ret; (void) type; if (-1 == _SLang_pop_struct (&s)) return -1; if (NULL == (f = pop_field (s, name, find_field))) { _SLstruct_delete_struct (s); return -1; } ret = _SLpush_slang_obj (&f->obj); _SLstruct_delete_struct (s); return ret;}static int struct_typecast (unsigned char a_type, VOID_STAR ap, unsigned int na, unsigned char b_type, VOID_STAR bp){ _SLang_Struct_Type **a, **b; unsigned int i; (void) a_type; (void) b_type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -