/*
This file is part of the FElt finite element analysis package.
Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/************************************************************************
* File: field.c *
* *
* Description: This file contains the public and private function *
* definitions relating to record fields and the *
* corresponding virtual machine instruction. *
************************************************************************/
# include "debug.h"
# include "error.h"
# include "field.h"
# include "execute.h"
# define MaxFields 160
typedef struct field {
short type;
short handler;
short offset;
} *Field;
static struct field field_table [D_NumTypes] [MaxFields];
/************************************************************************
* Function: add_field *
* *
* Description: Adds a field to the field table. The table is a two- *
* dimensional array indexed by type and field number. *
************************************************************************/
void add_field (rtype, name, ftype, offset, handler)
int rtype;
char *name;
int ftype;
unsigned offset;
TrapHandler handler;
{
ste *s;
Field f;
s = st_insert (&field_st, name, FieldOp);
if (s -> idx >= MaxFields) {
rterror ("too may field entries");
exit (1);
}
f = &field_table [rtype] [s -> idx];
f -> type = ftype;
f -> offset = offset;
f -> handler = AddTrap (handler);
}
/************************************************************************
* Function: field_op *
* *
* Description: Pops the descriptor on the top of the stack, looks up *
* the field whose given at the next address, and places *
* the result on the stack. If the field type is an array *
* then the appropriate array constructor is called. If *
* the field is a pair then the offset is added to the *
* current pointer. Otherwise, the current pointer is *
* first dereferenced and then the offset is added. *
************************************************************************/
int field_op ( )
{
void *ptr;
descriptor *record;
descriptor *result;
descriptor temp;
int type_error;
int index;
Field f;
result = top ( );
temp = *result;
record = &temp;
index = fetch (pc ++).ival;
record = deref (record);
if ((f = &field_table [D_Type (record)] [index]) -> type != T_Null) {
type_error = F_False;
ptr = D_Pointer (record);
if (ptr && (D_Direct (record) || *(char **) ptr)) {
switch (D_Type (record)) {
case T_Analysis:
case T_Pair:
case T_Problem:
ptr = (void *) ((char *) D_Pointer (record) + f -> offset);
break;
default:
ptr = (void *) (*(char **) D_Pointer (record) + f -> offset);
break;
}
if (f -> type != T_Array) {
D_Type (result) = f -> type;
D_Temp (result) = F_False;
D_Trapped (result) = f -> handler;
D_Pointer (result) = ptr;
} else {
CreateData (result, NULL, NULL, T_Array, ptr, 0, T_Null, 0);
CallTrap (f -> handler, record, &result);
}
} else {
D_Type (result) = T_Null;
D_Temp (result) = F_False;
D_Trapped (result) = F_False;
D_Pointer (result) = NULL;
}
} else {
type_error = F_True;
TypeError ("has no such field", record, NULL, NULL, F_False);
}
RecycleData (record);
d_printf ("field ans =\n");
d_PrintData (result);
return type_error == F_True;
}
syntax highlighted by Code2HTML, v. 0.9.1