www.pudn.com > LightTrack.rar > data.cpp
/** 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/* FILE etc. */ #include /* cmpstr etc. */ #include /* 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 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 = | | | | | * * | <[>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_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 " */ 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 statements, constructing variables on * * statements processing stops on first export statement.* * * * source = name type | * * | type name var | * * | 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_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_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