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_current2)&&(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