www.pudn.com > RayTrace.rar > data.cpp, change:2006-07-21,size:32377b
/** 3DGPL *************************************************\
* () *
* Interpreting ascii data description, constructing a *
* data structure in memory, atempting to do correct *
* alignment for items in the structs. *
* *
* Defines: *
* D_data Getting a specified export. *
* *
* Internals: *
* DI_char Next char of the source; *
* DI_token Next token of the stream; *
* DI_type Interpreting type; *
* DI_var Interpreting var list; *
* DI_length Length of type in bytes. *
* *
* (c) 1995-98 Sergei Savchenko, (savs@cs.mcgill.ca) *
\**********************************************************/
//data.cpp
#include "LightTrack.h" /* HW_error */
#include "data.h" /* self definition */
#include <stdio.h> /* FILE etc. */
#include <string.h> /* cmpstr etc. */
#include <stdlib.h> /* malloc etc. */
#define D_MAX_TOKEN_LENGTH 100 /* token taken from the source */
#define D_NAME_LENGTH 32 /* names gotta be this long */
#define D_BUFFER_LENGTH 256 /* chars being read */
enum D_token_type /* enumerates all tokens */
{
D_EOF, /* end of file */
D_NAME, /* starting from the letter */
D_NUMBER, /* starting from a number */
D_NUMBERF, /* starting from a float number */
D_BASE_INT, /* base types */
D_BASE_FLOAT,
D_BASE_SHORT,
D_BASE_BYTE,
D_BASE_PTR, /* typeless pointer */
D_DEREF, /* dereferencing symbol */
D_OPEN_SQ, /* describes an array */
D_CLOSE_SQ,
D_OPEN_CURL, /* describes a structure */
D_CLOSE_CURL,
D_OPEN_RAW, /* describes a raw data array */
D_CLOSE_RAW,
D_STATE_TYPE, /* statements */
D_STATE_VAR, /* "name" */
D_STATE_EXPORT
};
struct D_token /* describes a token */
{
char d_description[D_MAX_TOKEN_LENGTH]; /* actual text of a token */
enum D_token_type d_type; /* enumeration of this token */
};
struct D_token D_tokens[]= /* what is in the grammer */
{
{"int" ,D_BASE_INT}, /* base types */
{"float" ,D_BASE_FLOAT},
{"short" ,D_BASE_SHORT},
{"byte" ,D_BASE_BYTE},
{"ptr" ,D_BASE_PTR},
{"@" ,D_DEREF}, /* dereferencing symbol */
{"[" ,D_OPEN_SQ}, /* array */
{"]" ,D_CLOSE_SQ},
{"{" ,D_OPEN_CURL}, /* structure */
{"}" ,D_CLOSE_CURL},
{"<" ,D_OPEN_RAW}, /* raw array */
{">" ,D_CLOSE_RAW},
{"type" ,D_STATE_TYPE}, /* statements */
{"var" ,D_STATE_VAR},
{"export",D_STATE_EXPORT},
{"" ,(D_token_type)0} /* tagging the last one */
};
char D_terminators[]=" \n\r@[]{}<>\xff"; /* expression terminators */
char D_filters[]=" \n\r"; /* characters which are ignored */
int D_current; /* char being read */
int D_last; /* how many chars are there */
int D_line; /* number of lines read */
char *D_buffer; /* the chars being read */
FILE *D_file; /* handle to the input */
char D_fname[D_NAME_LENGTH]; /* name of the current file */
struct D_int_alignment_struct { char d_char; int d_int; } D_int_check;
struct D_float_alignment_struct { char d_char; float d_float; } D_float_check;
struct D_short_alignment_struct { char d_char; short d_short; } D_short_check;
struct D_ptr_alignment_struct { char d_char; char *d_ptr; } D_ptr_check;
int D_int_alignment; /* alignment type for int */
int D_float_alignment; /* alignment type for int */
int D_short_alignment; /* alignment type for int */
int D_ptr_alignment; /* gotta be same as int but... */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Stream of chars from the script file. *
* *
* RETURNS: Next character from the script stream. *
* -------- *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char DI_char(void)
{
if(D_current<D_last) /* as long as have something */
{
return(D_buffer[D_current++]); /* current char */
}
else
{
if((D_last=fread(D_buffer,sizeof(char),D_BUFFER_LENGTH,D_file))==0)
return('\xff'); /* end of the source */
D_current=0; /* starting from the first one */
return(D_buffer[D_current++]);
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Tokenizer. token is defined as a text between *
* a filter ( ignored ) and a terminator. token might *
* be a terminator. *
* *
* RETURNS: Type of the current token. *
* -------- *
* SETS: D_token_text,D_token_number for some kinds of *
* ----- tokens, D_line would have number of \n read. *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char D_token_text[D_MAX_TOKEN_LENGTH]; /* set after DI_token */
int D_token_number;
float D_token_numberf;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum D_token_type DI_token(void)
{
int i,lng=0; /* empty yet */
char c;
for(;;) /* ignore preceding filters */
{
c=DI_char();
if(c=='\xff') /* end of input strem */
{
D_token_text[lng]=0; /* no text associated here */
return(D_EOF); /* end of the source */
}
for(i=0;D_filters[i]!=0;i++)
if(c==D_filters[i]) break; /* yes, filter current symbol */
if(D_filters[i]==0)
{
D_current--; /* process further */
break; /* nope, none of filters */
}
if(D_filters[i]=='\n') D_line++; /* counter of lines read */
}
for(;;) /* copy until the terminator */
{
c=DI_char();
for(i=0;D_terminators[i]!=0;i++)
if(c==D_terminators[i]) break; /* yes, terminate on this one */
if(D_terminators[i]==0) /* not a terminator */
{
D_token_text[lng++]=c; /* char in the token */
}
else /* yes a terminator */
{
D_token_text[lng]=0; /* end of line */
D_current--; /* process a terminator further */
break; /* finished composing a token */
}
}
if(lng==0) /* checking tokens/terminators */
{
for(i=0;strlen(D_tokens[i].d_description)!=0;i++)
if(strncmp(D_tokens[i].d_description,&c,1)==0)
{
D_current++; /* don't process on the next step */
return(D_tokens[i].d_type);
}
}
for(i=0;strlen(D_tokens[i].d_description)!=0;i++)
if(strcmp(D_tokens[i].d_description,D_token_text)==0)
return(D_tokens[i].d_type); /* command token */
if(strchr(D_token_text,'.')!=NULL)
{
if(sscanf(D_token_text,"%f",&D_token_numberf)==1)
return(D_NUMBERF); /* is floating point */
}
if((lng>2)&&(D_token_text[0]=='0')&&
(D_token_text[1]=='x')) /* 0x0 hexadecimal */
{
if(sscanf(D_token_text+2,"%x",&D_token_number)==1)
return(D_NUMBER); /* is hexadecimal */
}
if(sscanf(D_token_text,"%d",&D_token_number)==1)
return(D_NUMBER); /* is decimal */
return(D_NAME); /* can be only a name */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* The processing of the token stream from the moment *
* the function is called should relate to type *
* description as follows: *
* *
* type = <int> | <float> | <short> | <byte> | <ptr> | *
* | <[>number<]>type | <{> type {type} <}> *
* *
* RETURNS: Number of the type just created. *
* -------- *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct D_type_name /* relates type name and number */
{
char d_name[D_NAME_LENGTH]; /* type name */
int d_type; /* type number */
};
struct D_type /* describes a type */
{
int d_array; /* number of elements or -1 */
int d_next; /* next item or -1 */
int d_current; /* this type */
};
struct D_var_name /* description of a variable */
{
char d_name[D_NAME_LENGTH]; /* name of a variable */
char *d_data; /* allocated data */
int d_type; /* type of a variable */
};
#define D_SINGULAR 0 /* not an array type */
#define D_NONE -1 /* kinda internal NULL */
#define D_TYPE_INT -2 /* base types: integer */
#define D_TYPE_FLOAT -3
#define D_TYPE_SHORT -4
#define D_TYPE_BYTE -5 /* byte */
#define D_TYPE_PTR -6 /* and pointer */
#define D_MAX_TYPES 512 /* sizes for tables */
#define D_MAX_VAR_NAMES 512
#define D_MAX_TYPE_NAMES 512
struct D_type_name *D_type_names; /* relates names to numbers */
int D_no_type_names; /* number of names */
struct D_type *D_types; /* all types */
int D_no_types; /* number of all types */
struct D_var_name *D_var_names; /* all variable names */
int D_no_var_names; /* number of variables */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int DI_type(void)
{
int prev,orig=0,tp,i;
switch(DI_token())
{
case D_NAME: for(i=0;i<D_no_type_names;i++)
if(strcmp(D_token_text,D_type_names[i].d_name)==0)
return(D_type_names[i].d_type);
HW_error("(%s:%d) Unknown type name: %s\n",D_fname,D_line,D_token_text);
break;
case D_BASE_INT: return(D_TYPE_INT); /* base type int */
case D_BASE_FLOAT: return(D_TYPE_FLOAT); /* base type float */
case D_BASE_SHORT:return(D_TYPE_SHORT); /* base type short */
case D_BASE_BYTE: return(D_TYPE_BYTE); /* byte type byte */
case D_BASE_PTR: return(D_TYPE_PTR); /* base type typeless ptr */
case D_OPEN_SQ: if(DI_token()!=D_NUMBER)/* array [N] */
HW_error("(%s:%d) Number expected.\n",D_fname,D_line);
D_types[D_no_types].d_array=D_token_number;
D_types[tp=D_no_types++].d_next=-1;
if(D_no_types>=D_MAX_TYPES)
HW_error("(Data) No space in type list.\n");
if(DI_token()!=D_CLOSE_SQ)
HW_error("(%s:%d) Closing bracket expected.\n",
D_fname,D_line
);
D_types[tp].d_current=DI_type();
return(tp); /* was an array type */
case D_OPEN_CURL: prev=D_NONE; /* no first in the chain yet */
while((tp=DI_type())!=D_NONE)
{
D_types[D_no_types].d_array=D_SINGULAR;
D_types[D_no_types].d_current=tp;
tp=D_no_types++; /* just created type is */
if(D_no_types>=D_MAX_TYPES)
HW_error("(Data) No space in type list.\n");
if(prev!=D_NONE) /* extending the chain */
D_types[prev].d_next=tp;
else
orig=tp; /* head of the chain */
prev=tp; /* to allow extention further */
}
D_types[prev].d_next=D_NONE;
return(orig); /* head of the chain */
case D_CLOSE_CURL:return(D_NONE); /* no more types in the list */
default: HW_error("(%s:%d) Type defenition expected.\n",
D_fname,D_line
);
}
return(D_NONE); /* would never happen, actually */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* The processing of the token stream from the moment *
* the function is called should correspond to passed *
* type and relate to variable defenition as follows: *
* *
* var = number | reference | @reference | file_name | *
* | <[> var {var} <]> | <{> var {var} <}> *
* *
* RETURNS: Number of bytes filled by the definition. *
* -------- *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int DI_var(int type,char* space)
{
enum D_token_type tp;
char *orig_space=space; /* where the start was */
int i;
if(type==D_TYPE_BYTE) /* base type byte */
{
switch(DI_token()) /* number or @name */
{
case D_NUMBER: *(char*)space=(char)D_token_number;
return(sizeof(char));
case D_DEREF: DI_token(); /* getting name */
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names)
HW_error("(%s:%d) Unknown name %s.\n",
D_fname,D_line,D_token_text
);
if(D_var_names[i].d_type!=D_TYPE_BYTE)
HW_error("(%s:%d) %s Expected to be a constant.\n",
D_fname,D_line,D_token_text
);
*(char*)space=*(char*)D_var_names[i].d_data;
return(sizeof(char));
default: HW_error("(%s:%d) Constant expected.\n",D_fname,D_line);
}
}
if(type==D_TYPE_SHORT) /* base type short */
{
if(((long)space)%D_short_alignment!=0)
space+=D_short_alignment-((long)space)%D_short_alignment;
switch(DI_token()) /* number of @name */
{
case D_NUMBER: *(short*)space=(short)D_token_number;
space+=sizeof(short);
return(space-orig_space); /* pointer difference */
case D_DEREF: DI_token(); /* getting name */
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names)
HW_error("(%s:%d) Unknown name %s.\n",
D_fname,D_line,D_token_text
);
if(D_var_names[i].d_type!=D_TYPE_SHORT)
HW_error("(%s:%d) %s Expected to be a constant.\n",
D_fname,D_line,D_token_text
);
*(short*)space=*(short*)D_var_names[i].d_data;
space+=sizeof(short);
return(space-orig_space); /* pointer difference */
default: HW_error("(%s:%d) Constant expected.\n",D_fname,D_line);
}
}
if(type==D_TYPE_INT) /* base type int */
{
if(((long)space)%D_int_alignment!=0)
space+=D_int_alignment-((long)space)%D_int_alignment;
switch(DI_token()) /* number of @name */
{
case D_NUMBER: *(int*)space=D_token_number;
space+=sizeof(int);
return(space-orig_space); /* pointer difference */
case D_DEREF: DI_token(); /* getting name */
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names)
HW_error("(%s:%d) Unknown name %s.\n",
D_fname,D_line,D_token_text
);
if(D_var_names[i].d_type!=D_TYPE_INT)
HW_error("(%s:%d) %s Expected to be a constant.\n",
D_fname,D_line,D_token_text
);
*(int*)space=*(int*)D_var_names[i].d_data;
space+=sizeof(int);
return(space-orig_space); /* pointer difference */
default: HW_error("(%s:%d) Constant expected.\n",D_fname,D_line);
}
}
if(type==D_TYPE_FLOAT) /* base type float */
{
if(((long)space)%D_float_alignment!=0)
space+=D_float_alignment-((long)space)%D_float_alignment;
switch(DI_token()) /* number of @name */
{
case D_NUMBERF:*(float*)space=D_token_numberf;
space+=sizeof(float);
return(space-orig_space); /* pointer difference */
case D_NUMBER: *(float*)space=(float)D_token_number;
space+=sizeof(float);
return(space-orig_space); /* pointer difference */
case D_DEREF: DI_token(); /* getting name */
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names)
HW_error("(%s:%d) Unknown name %s.\n",
D_fname,D_line,D_token_text
);
if(D_var_names[i].d_type!=D_TYPE_FLOAT)
HW_error("(%s:%d) %s Expected to be a constant.\n",
D_fname,D_line,D_token_text
);
*(float*)space=*(float*)D_var_names[i].d_data;
space+=sizeof(float);
return(space-orig_space); /* pointer difference */
default: HW_error("(%s:%d) Constant expected.\n",D_fname,D_line);
}
}
if(type==D_TYPE_PTR) /* base type pointer */
{
if(((long)space)%D_ptr_alignment!=0)
space+=D_ptr_alignment-((long)space)%D_ptr_alignment;
switch(DI_token()) /* 0 or @name or name */
{
case D_NUMBER: if(D_token_number!=0)
HW_error("(%s:%d) Only \"0\" allowed as a pointer.\n",
D_fname,D_line
);
*(char**)space=NULL; /* 0 == NULL */
space+=sizeof(char*);
return(space-orig_space); /* pointer difference */
case D_NAME: for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names) /* not a name, a file? */
{
int DD_current=D_current;/* stack of globals for */
int DD_last=D_last; /* recursive call to D_data */
int DD_line=D_line;
char *DD_buffer=D_buffer;
FILE *DD_file=D_file;
struct D_type_name *DD_type_names=D_type_names;
int DD_no_type_names=D_no_type_names;
struct D_type *DD_types=D_types;
int DD_no_types=D_no_types;
struct D_var_name *DD_var_names=D_var_names;
int DD_no_var_names=D_no_var_names;
char DD_fname[D_NAME_LENGTH];
strncpy(DD_fname,D_fname,D_NAME_LENGTH);
if(strcmp(DD_fname,D_token_text)==0)
HW_error("(%s:%d) Can't recurse files, think about it.\n",
D_fname,D_line
);
*(char**)space=(char *)D_data(D_token_text);
strncpy(D_fname,DD_fname,D_NAME_LENGTH);
D_no_var_names=DD_no_var_names;
D_var_names=DD_var_names;
D_no_types=DD_no_types;
D_types=DD_types;
D_no_type_names=DD_no_type_names;
D_type_names=DD_type_names;
D_file=DD_file;
D_buffer=DD_buffer;
D_line=DD_line;
D_last=DD_last;
D_current=DD_current; /* restoring globals from stack */
}
else /* a name */
{
*(char**)space=D_var_names[i].d_data;
}
space+=sizeof(char*);
return(space-orig_space); /* pointer difference */
case D_DEREF: DI_token(); /* getting name */
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names)
HW_error("(%s:%d) Unknown name %s.\n",
D_fname,D_line,D_token_text
);
if(D_var_names[i].d_type!=D_TYPE_PTR)
HW_error("(%s:%d) %s Expected to be a constant pointer.\n",
D_fname,D_line,D_token_text
);
*(char**)space=*(char**)D_var_names[i].d_data;
space+=sizeof(char*);
return(space-orig_space); /* pointer difference */
default: HW_error("(%s:%d) Name or \"0\" expected.\n",D_fname,D_line);
}
}
if(D_types[type].d_array!=D_SINGULAR) /* type is an array */
{
tp=DI_token();
if(tp==D_OPEN_RAW) /* raw byte array */
{
if(D_types[type].d_current!=D_TYPE_BYTE) /* raw array starts with "<" */
HW_error("(%s:%d) Raw array is allowed only for bytes.\n",D_fname,D_line);
for(i=0;i<D_types[type].d_array;i++,space++)
*space=DI_char();
if(DI_token()!=D_CLOSE_RAW) /* raw array ends with ">" */
HW_error("(%s:%d) Closing bracket expected.\n",D_fname,D_line);
return(space-orig_space); /* pointer difference */
}
else
{
if(tp!=D_OPEN_SQ) /* array starts with "[" */
HW_error("(%s:%d) Opening bracket expected.\n",D_fname,D_line);
for(i=0;i<D_types[type].d_array;i++) /* processing elements */
space+=DI_var(D_types[type].d_current,space);
if(DI_token()!=D_CLOSE_SQ) /* array ends with "]" */
HW_error("(%s:%d) Closing bracket expected.\n",D_fname,D_line);
return(space-orig_space); /* pointer difference */
}
}
if(D_types[type].d_next!=D_NONE) /* a structure? */
{
if(DI_token()!=D_OPEN_CURL) /* struct starts with "{" */
HW_error("(%s:%d) Opening bracket expected.\n",D_fname,D_line);
for(;type!=D_NONE;type=D_types[type].d_next)
space+=DI_var(D_types[type].d_current,space);
if(DI_token()!=D_CLOSE_CURL) /* struct ends with "}" */
HW_error("(%s:%d) Closing bracket expected.\n",D_fname,D_line);
return(space-orig_space); /* pointer difference */
}
return(space-orig_space); /* pointer difference */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Size of a type defined in types table. *
* *
* RETURNS: Length in bytes of the requested type. *
* -------- *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int DI_length(int type,int current_length)
{
int alignment,lng=0;
if(type==D_TYPE_BYTE) return(sizeof(char));/* base types */
if(type==D_TYPE_SHORT)
{
if(current_length%D_short_alignment==0) alignment=0;
else alignment=D_short_alignment-current_length%D_short_alignment;
return(sizeof(short)+alignment);
}
if(type==D_TYPE_INT)
{
if(current_length%D_int_alignment==0) alignment=0;
else alignment=D_int_alignment-current_length%D_int_alignment;
return(sizeof(int)+alignment);
}
if(type==D_TYPE_FLOAT)
{
if(current_length%D_float_alignment==0) alignment=0;
else alignment=D_float_alignment-current_length%D_float_alignment;
return(sizeof(float)+alignment);
}
if(type==D_TYPE_PTR)
{
if(current_length%D_ptr_alignment==0) alignment=0;
else alignment=D_ptr_alignment-current_length%D_ptr_alignment;
return(sizeof(char*)+alignment);
}
if(D_types[type].d_array!=D_SINGULAR) /* type is an array */
{ /* first item might be aligned */
alignment=DI_length(D_types[type].d_current,current_length);
return((D_types[type].d_array-1)*DI_length(D_types[type].d_current,0)+
alignment
);
}
if(D_types[type].d_next!=D_NONE) /* a structure? */
{
for(;type!=D_NONE;type=D_types[type].d_next)
lng+=DI_length(D_types[type].d_current,lng);
}
return(lng);
}
/*********************************************************\
* Processing specified input file remembering type info *
* in <type> statements, constructing variables on <var> *
* statements processing stops on first export statement.*
* *
* source = <type> name type | *
* | <var> type name var | *
* | <export> name *
* *
* RETURNS: Pointer to data specified in first export. *
* -------- *
\*********************************************************/
void* D_data(char *name)
{
char *data=NULL; /* pointer to be returned */
int tp,i,quit=0; /* flag when to quit */
long lng;
D_int_alignment=((char*)&D_int_check.d_int)-((char*)&D_int_check.d_char);
D_float_alignment=((char*)&D_float_check.d_float)-((char*)&D_float_check.d_char);
D_short_alignment=((char*)&D_short_check.d_short)-((char*)&D_short_check.d_char);
D_ptr_alignment=((char*)&D_ptr_check.d_ptr)-((char*)&D_ptr_check.d_char);
strncpy(D_fname,name,D_NAME_LENGTH); /* for error messages */
if((D_file=fopen(name,"rb"))==NULL) /* where to take data from */
HW_error("(Data) Can't open %s.\n",D_fname);
D_current=D_last=0; /* the buffer is empty */
D_line=1; /* initally at first line */
D_buffer=(char*)malloc(D_BUFFER_LENGTH*sizeof(char));
if(D_buffer==NULL) HW_error("(Data) Not enough memory.\n");
D_type_names=(struct D_type_name*)malloc(D_MAX_TYPE_NAMES*
sizeof(struct D_type_name));
D_types=(struct D_type*)malloc(D_MAX_TYPES*sizeof(struct D_type));
D_var_names=(struct D_var_name*)malloc(D_MAX_VAR_NAMES*
sizeof(struct D_var_name));
if((D_type_names==NULL)||(D_types==NULL)||(D_var_names==NULL))
HW_error("(Data) Not enough memory.\n");
D_no_type_names=D_no_types=D_no_var_names=0;/* all tables are empty */
do
{
switch(DI_token())
{
case D_STATE_TYPE: if(DI_token()!=D_NAME)
HW_error("(%s:%d) Name expected.\n",D_fname,D_line);
for(i=0;i<D_no_type_names;i++)
if(strcmp(D_token_text,D_type_names[i].d_name)==0)
HW_error("(%s:%d) Duplicate type name %s.\n",
D_fname,D_line,D_token_text
);
strncpy(D_type_names[D_no_type_names].d_name,
D_token_text,D_NAME_LENGTH
);
D_type_names[D_no_type_names++].d_type=DI_type();
if(D_no_type_names>=D_MAX_TYPE_NAMES)
HW_error("(Data) No space in type table.\n");
break;
case D_STATE_VAR: D_var_names[D_no_var_names].d_data=(char*)
malloc(lng=sizeof(char)*DI_length(tp=DI_type(),0));
if(D_var_names[D_no_var_names].d_data==NULL)
HW_error("(Data) Not enough memory %ld.\n",lng);
D_var_names[D_no_var_names].d_type=tp;
if(DI_token()!=D_NAME)
HW_error("(%s:%d) Name expected.\n",D_fname,D_line);
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0)
HW_error("(%s:%d) Duplicate variable name %s.\n",
D_fname,D_line,D_token_text
);
strncpy(D_var_names[D_no_var_names].d_name,
D_token_text,D_NAME_LENGTH
);
DI_var(tp,D_var_names[D_no_var_names++].d_data);
if(D_no_var_names>=D_MAX_VAR_NAMES)
HW_error("(Data) No space in var table.\n");
break;
case D_STATE_EXPORT:if(DI_token()!=D_NAME)
HW_error("(%s:%d) Name expected.\n",D_fname,D_line);
for(i=0;i<D_no_var_names;i++)
if(strcmp(D_token_text,D_var_names[i].d_name)==0) break;
if(i==D_no_var_names)
HW_error("(%s:%d) Unknown variable name %s.\n",
D_fname,D_line,D_token_text
);
data=D_var_names[i].d_data;
quit=1; /* quit processing */
break;
default: HW_error("(%s:%d) No such statement %s.\n",
D_fname,D_line,D_token_text
);
}
} while(!quit);
fclose(D_file);
free(D_buffer); /* getting rid of all tables */
free(D_type_names);
free(D_types);
free(D_var_names);
return(data); /* constructed structure */
}
/**********************************************************/