51 #define isblank(a) (a == ' ' || a == '\t') 56 #define TOKEN_ERR(z, l) \ 57 PRINT_ERR2("%s:%d : " z, this->filename.c_str(), l) 58 #define PARSE_ERR(z, l) \ 59 PRINT_ERR2("%s:%d : " z, this->filename.c_str(), l) 71 unit_angle( M_PI / 180.0 )
88 FILE *fp = fopen(filename.c_str(), method);
96 char *stagepath = getenv(
"STAGEPATH");
97 char *token = strtok(stagepath,
":");
98 char* fullpath =
new char[PATH_MAX];
99 char *tmp = strdup(filename.c_str());
101 while (token != NULL) {
103 memset( fullpath, 0, PATH_MAX);
104 strcat( fullpath, token);
105 strcat( fullpath,
"/" );
106 strcat( fullpath, base);
107 assert(strlen(fullpath) + 1 < PATH_MAX);
108 fp = fopen(fullpath, method);
110 this->filename = std::string(fullpath);
115 token = strtok(NULL,
":");
118 if( fullpath )
delete[] fullpath;
131 FILE *file =
FileOpen(this->filename.c_str(),
"r");
134 PRINT_ERR2(
"unable to open world file %s : %s",
135 this->filename.c_str(), strerror(errno));
159 if (
ReadInt(0,
"test", 0) != 0)
161 PRINT_ERR(
"this is a test file; quitting");
170 const std::string& unitl =
ReadString(0,
"unit_length",
"m");
173 else if( unitl ==
"cm")
175 else if( unitl ==
"mm")
179 const std::string& unita =
ReadString(0,
"unit_angle",
"degrees");
180 if( unita ==
"degrees")
182 else if( unita ==
"radians")
199 FILE *file = fopen(filename.c_str(),
"w+");
203 PRINT_ERR2(
"unable to open world file %s : %s",
204 filename.c_str(), strerror(errno));
230 if( ! it->second->used )
232 PRINT_WARN3(
"worldfile %s:%d : property [%s] is defined but not used",
233 this->
filename.c_str(), it->second->line, it->second->name.c_str());
258 if ((
char) ch ==
'#')
264 else if (isalpha(ch))
270 else if (strchr(
"+-.0123456789", ch))
288 else if (strchr(
"(", ch))
294 else if (strchr(
")", ch))
300 else if (strchr(
"[", ch))
306 else if (strchr(
"]", ch))
312 else if ( 0x0d == ch )
320 else if ( 0x0a == ch )
348 memset(token, 0,
sizeof(token));
359 else if ( 0x0a == ch || 0x0d == ch )
381 memset(token, 0,
sizeof(token));
392 else if (isalpha(ch) || isdigit(ch) || strchr(
".-_[]", ch))
398 if (strcmp(token,
"include") == 0)
430 TOKEN_ERR(
"incomplete include statement", *line);
435 TOKEN_ERR(
"syntax error in include statement", *line);
447 TOKEN_ERR(
"incomplete include statement", *line);
452 TOKEN_ERR(
"syntax error in include statement", *line);
465 if (filename[0] ==
'/' || filename[0] ==
'~')
467 fullpath = strdup(filename);
469 else if (this->filename[0] ==
'/' || this->filename[0] ==
'~')
474 char *tmp = strdup(this->filename.c_str());
475 fullpath =
new char[PATH_MAX];
476 memset(fullpath, 0, PATH_MAX);
477 strcat( fullpath,
dirname(tmp));
478 strcat( fullpath,
"/" );
479 strcat( fullpath, filename );
480 assert(strlen(fullpath) + 1 < PATH_MAX);
488 char *tmp = strdup(this->filename.c_str());
489 fullpath =
new char[PATH_MAX];
490 char* dummy = getcwd(fullpath, PATH_MAX);
493 PRINT_ERR2(
"unable to get cwd %d: %s", errno, strerror(errno));
498 strcat( fullpath,
"/" );
499 strcat( fullpath,
dirname(tmp));
500 strcat( fullpath,
"/" );
501 strcat( fullpath, filename );
502 assert(strlen(fullpath) + 1 < PATH_MAX);
506 printf(
"[Include %s]", filename );
510 FILE *infile =
FileOpen(fullpath,
"r");
513 PRINT_ERR2(
"unable to open include file %s : %s",
514 fullpath, strerror(errno));
557 memset(token, 0,
sizeof(token));
568 else if (strchr(
"+-.0123456789", ch))
593 memset(token, 0,
sizeof(token));
601 if ( EOF == ch || 0x0a == ch || 0x0d == ch )
603 TOKEN_ERR(
"unterminated string constant", *line);
630 memset(token, 0,
sizeof(token));
664 for (i = 0; i < this->
tokens.size(); i++)
671 fprintf(file,
"\"%s\"", token->
value.c_str());
673 fprintf(file,
"%s", token->
value.c_str());
700 assert(index >= 0 && index < (
int)this->
tokens.size() );
701 tokens[index].value = value;
710 assert(index >= 0 && index < (
int)this->
tokens.size());
711 return this->
tokens[index].value.c_str();
722 printf(
"\n## begin tokens\n");
723 printf(
"## %4d : ", line);
728 if ( it->value[0] ==
'\n')
729 printf(
"[\\n]\n## %4d : %02d ", ++line, it->include);
731 printf(
"[%s] ", it->value.c_str());
734 printf(
"## end tokens\n");
754 for (i = 0; i < (int)this->
tokens.size(); i++)
756 token = &this->
tokens[0] + i;
761 if ( token->
value ==
"include")
766 else if ( token->
value ==
"define" )
800 for (i = *index + 1; i < (int)this->
tokens.size(); i++)
815 PARSE_ERR(
"syntax error in include statement", *line);
819 PARSE_ERR(
"incomplete include statement", *line);
830 const char *macroname, *entityname;
839 for (i = *index + 1; i < (int)this->
tokens.size(); i++)
848 if (macroname == NULL)
850 else if (entityname == NULL)
857 PARSE_ERR(
"extra tokens in macro definition", *line);
863 if (macroname == NULL)
865 PARSE_ERR(
"missing name in macro definition", *line);
868 if (entityname == NULL)
870 PARSE_ERR(
"missing name in macro definition", *line);
882 AddMacro(macroname, entityname, *line, starttoken, i);
908 for (i = *index + 1; i < (int)this->
tokens.size(); i++)
952 int nentity = this->
entities.size();
954 int mline = macro->
line;
959 for (i = *index + 1; i < (int)this->
tokens.size(); i++)
992 for (i = *index + 1; i < (int)this->
tokens.size(); i++)
1034 for(
int i = *index + 1; i < (int)this->
tokens.size(); i++)
1036 token = &this->
tokens[i];
1038 switch (token->
type)
1071 unsigned int i, count;
1076 for (i = *index + 1; i < this->
tokens.size(); i++)
1078 token = &this->
tokens[i];
1080 switch (token->
type)
1115 int line,
int starttoken,
int endtoken)
1117 macros.insert( std::pair<std::string,CMacro>( macroname,
CMacro( macroname, entityname, line, starttoken, endtoken )));
1126 std::map<std::string,CMacro>::iterator it =
macros.find( macroname );
1139 printf(
"\n## begin macros\n");
1144 CMacro *macro = &(it->second);
1147 for (
int j = macro->
starttoken; j <= macro->endtoken; j++)
1156 printf(
"## end macros\n");
1206 if (entity < 0 || entity >= (
int)this->
entities.size())
1208 return this->
entities[entity].parent;
1216 if (entity < 0 || entity >= (
int)this->
entities.size())
1218 return this->
entities[entity].type.c_str();
1239 printf(
"Print key %s prop ent %d name %s\n", key, prop->
entity, prop->
name.c_str() );
1246 printf(
"\n## begin entities\n");
1249 PrintProp( it->first.c_str(), it->second );
1251 printf(
"## end entities\n");
1270 snprintf( key, 127,
"%d%s", entity, name );
1288 if( index >= (
int)property->
values.size() )
1289 property->
values.resize( index+1 );
1291 property->values[index] = value_token;
1301 snprintf( key, 127,
"%d%s", entity, name );
1305 static char cache_key[128] = { 0 };
1306 static CProperty* cache_property = NULL;
1308 if( strncmp( key, cache_key, 128 ) != 0 )
1310 strncpy( cache_key, key, 128 );
1312 std::map<std::string,CProperty*>::iterator it =
properties.find( key );
1314 cache_property = NULL;
1316 cache_property = it->second;
1321 return cache_property;
1338 assert(index >= 0 && index < (
int)property->
values.size() );
1348 property->used =
true;
1357 printf(
"\n## begin properties\n");
1370 printf(
"## end properties\n");
1379 if (property == NULL )
1390 if( property == NULL )
1401 if (property == NULL )
1411 char default_str[64];
1412 snprintf(default_str,
sizeof(default_str),
"%d", value);
1421 if( fabs(value) < 0.001 )
1425 char default_str[64];
1426 snprintf(default_str,
sizeof(default_str),
"%.3f", value);
1437 if (property == NULL )
1453 if (property == NULL )
1457 if( filename[0] ==
'/' || filename[0] ==
'~' )
1460 else if (this->filename[0] ==
'/' || this->filename[0] ==
'~')
1465 char *tmp = strdup(this->filename.c_str());
1466 char* fullpath =
new char[PATH_MAX];
1467 memset(fullpath, 0, PATH_MAX);
1468 strcat( fullpath,
dirname(tmp));
1469 strcat( fullpath,
"/" );
1470 strcat( fullpath, filename );
1471 assert(strlen(fullpath) + 1 < PATH_MAX);
1481 char *tmp = strdup(this->filename.c_str());
1482 char* fullpath =
new char[PATH_MAX];
1483 char* dummy = getcwd(fullpath, PATH_MAX);
1486 PRINT_ERR2(
"unable to get cwd %d: %s", errno, strerror(errno));
1487 if( fullpath )
delete[] fullpath;
1488 if( tmp ) free(tmp);
1492 strcat( fullpath,
"/" );
1493 strcat( fullpath,
dirname(tmp));
1494 strcat( fullpath,
"/" );
1495 strcat( fullpath, filename );
1496 assert(strlen(fullpath) + 1 < PATH_MAX);
1507 const unsigned int first,
const unsigned int count,
const char* format, ... )
1510 if (property == NULL )
1513 if( property->values.size() < first+count )
1515 PRINT_ERR4(
"Worldfile: reading tuple \"%s\" index %u to %u - tuple has length %u\n",
1516 name, first, first+count-1, (
unsigned int)property->values.size() );
1520 if( strlen(format) != count )
1522 PRINT_ERR2(
"format string length %u does not match argument count %u",
1523 (
unsigned int)strlen(format), count );
1528 va_start( args, format );
1530 for(
unsigned int i=0; i<count; i++ )
1537 *va_arg( args,
int* ) = atoi(val);
1541 *va_arg( args,
unsigned int* ) = (
unsigned int)atoi(val);
1545 *va_arg( args,
double* ) = atof(val);
1549 *va_arg( args,
double* ) = atof(val) *
unit_length;
1553 *va_arg( args,
double* ) = atof(val) *
unit_angle;
1557 *va_arg( args,
char** ) = strdup(val);
1561 PRINT_ERR3(
"Unknown format character %c in string %s loading %s",
1562 format[i], format, name );
1574 const unsigned int first,
const unsigned int count,
const char* format, ... )
1577 if (property == NULL )
1580 if( property->values.size() < first+count )
1582 PRINT_ERR4(
"Worldfile: reading tuple \"%s\" index %d to %d - tuple has length %d\n",
1583 name, first, first+count-1, (
int)property->values.size() );
1587 if( strlen(format) != count )
1589 PRINT_ERR2(
"format string length %u does not match argument count %u",
1590 (
unsigned int)strlen(format), count );
1598 va_start( args, format );
1600 for(
unsigned int i=0; i<count; i++ )
1605 snprintf( buf,
sizeof(buf),
"%d", va_arg( args,
int ) );
1609 snprintf( buf,
sizeof(buf),
"%u", va_arg( args,
unsigned int ) );
1613 snprintf( buf,
sizeof(buf),
"%.3f", va_arg( args,
double ) );
1617 snprintf( buf,
sizeof(buf),
"%.3f", va_arg( args,
double ) /
unit_length );
1621 snprintf( buf,
sizeof(buf),
"%.3f", va_arg( args,
double ) /
unit_angle );
1625 strncpy( buf, va_arg( args,
char* ),
sizeof(buf) );
1626 buf[
sizeof(buf)-1] = 0;
1630 PRINT_ERR3(
"Unknown format character %c in string %s loading %s",
1631 format[i], format, name );
bool SetTokenValue(int index, const char *value)
std::string name
Name of property.
bool ParseTokenInclude(int *index, int *line)
std::map< std::string, CMacro > macros
bool LoadTokenSpace(FILE *file, int *line, int include)
bool ParseTokenEntity(int entity, int *index, int *line)
int GetEntityParent(int entity)
int LookupEntity(const char *type)
The Stage library uses its own namespace.
const char * GetEntityType(int entity)
bool LoadTokenWord(FILE *file, int *line, int include)
const char * basename(const char *filename)
bool LoadTokenInclude(FILE *file, int *line, int include)
const std::string ReadString(int entity, const char *name, const std::string &value)
CProperty * GetProperty(int entity, const char *name)
const char * GetPropertyValue(CProperty *property, int index)
const char * ReadFilename(int entity, const char *name, const char *value)
#define PRINT_WARN3(m, a, b, c)
int ReadTuple(const int entity, const char *name, const unsigned int first, const unsigned int num, const char *format,...)
bool LoadTokenString(FILE *file, int *line, int include)
void SetPropertyValue(CProperty *property, int index, const char *value)
bool ParseTokenTuple(CProperty *property, int *index, int *line)
void WriteInt(int entity, const char *name, int value)
void WriteTuple(const int entity, const char *name, const unsigned int first, const unsigned int count, const char *format,...)
CMacro * LookupMacro(const char *macroname)
bool Save(const std::string &filename)
char * dirname(char *path)
bool PropertyExists(int section, const char *token)
int entity
Index of entity this property belongs to.
bool LoadTokenNum(FILE *file, int *line, int include)
void AddPropertyValue(CProperty *property, int index, int value_token)
void WriteString(int entity, const char *name, const std::string &value)
void WriteFloat(int entity, const char *name, double value)
bool LoadTokens(FILE *file, int include)
bool SaveTokens(FILE *file)
const char * GetTokenValue(int index)
std::vector< CToken > tokens
#define PRINT_ERR3(m, a, b, c)
void PrintProp(const char *key, CProperty *prop)
bool ParseTokenWord(int entity, int *index, int *line)
void AddMacro(const char *macroname, const char *entityname, int line, int starttoken, int endtoken)
bool AddToken(int type, const char *value, int include)
#define PRINT_DEBUG1(m, a)
double ReadFloat(int entity, const char *name, double value)
bool ParseTokenProperty(int entity, int *index, int *line)
#define PRINT_ERR2(m, a, b)
int ReadInt(int entity, const char *name, int value)
int AddEntity(int parent, const char *type)
#define PRINT_ERR4(m, a, b, c, d)
bool Load(const std::string &filename)
std::vector< CEntity > entities
CProperty * AddProperty(int entity, const char *name, int line)
FILE * FileOpen(const std::string &filename, const char *method)
std::vector< int > values
A list of token indexes.
bool ParseTokenDefine(int *index, int *line)
bool LoadTokenComment(FILE *file, int *line, int include)
std::map< std::string, CProperty * > properties