home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
i
/
iritsm3s.zip
/
iritfltr
/
convdata.c
next >
Wrap
C/C++ Source or Header
|
1991-11-30
|
31KB
|
852 lines
/*****************************************************************************
* CONVDATA.C is an unsupported tool to help convert old (*.ply) data files *
* to the new (*.dat) format. This tool will be retired in future releases. *
* *
* To compile: *
* *
* Under MSDOS, using Borland/Turbo C: 'tcc -ml convdata.c' *
* *
* Under UNIX: 'cc -i convdata convdata.c' *
* *
* Usage: *
* *
* convdata < oldfile.ply > newfile.dat *
* *
* or *
* *
* convdata oldfile.ply > newfile.dat *
*****************************************************************************/
#ifdef __MSDOS__
#include <stdlib.h>
#include <conio.h>
#endif /* __MSDOS__ */
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#ifdef NO_VOID_PTR
#define VoidPtr char *
#else
#define VoidPtr void *
#endif /* NO_VOID_PTR */
#ifndef LINE_LEN
#define LINE_LEN 255
#endif LINE_LEN
#define NAME_LEN 6
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define FILE_TYPE_DATA 1
#define FILE_TYPE_VIEW 2
#define GEN_COPY(Dest, Src, Size) memcpy(Dest, Src, Size)
#define UNGET_STACK_SIZE 5
/*****************************************************************************
* Tokens definitions goes into here *
*****************************************************************************/
#define TOKEN_OPEN_PAREN 1
#define TOKEN_CLOSE_PAREN 2
#define TOKEN_NUMBER 10 /* Not used as number & names are decoded */
/* according to their places in grammer. */
#define TOKEN_VERTEX 20
#define TOKEN_POLYGON 21
#define TOKEN_POLYLINE 22
#define TOKEN_POINTLIST 23
#define TOKEN_OBJECT 24
#define TOKEN_COLOR 25
#define TOKEN_INTERNAL 26
#define TOKEN_NORMAL 27
#define TOKEN_PLANE 28
#define TOKEN_CBEZIER 29
#define TOKEN_SBEZIER 30
#define TOKEN_CNURB 31
#define TOKEN_SNURB 32
#define TOKEN_OTHER 100 /* Probably names & numbers. */
#define TOKEN_EOF -1
#define VERTEX_ENTRY 0x0001 /* Entry type, up to 16 types. */
#define POLYGON_ENTRY 0x0002
#define POLYLINE_ENTRY 0x0004
#define OBJECT_ENTRY 0x0008
#define COLOR_ENTRY 0x0010
#define POLYGON 1
#define POLYLINE 2
#define POINTLIST 3
/*****************************************************************************
* Parser error codes are following: *
*****************************************************************************/
#define P_ERR_NUMBER_EXPECTED 1
#define P_ERR_OPEN_PAREN_EXPECTED 2
#define P_ERR_CLOSE_PAREN_EXPECTED 3
#define P_ERR_LIST_COMP_UNDEF 4
#define P_ERR_UNDEF_EXPR_HEADER 5
#define P_ERR_NAME_TOO_LONG 6
#define P_ERR_PT_TYPE_EXPECTED 7
#define P_WRN_OBJ_NAME_TRUNC 100
/*****************************************************************************
* And some more definitions ... *
*****************************************************************************/
typedef unsigned char Byte;
typedef struct BinTree { /* The entries are saved as binary trees. */
struct BinTree *right, *left; /* Classic, isnt it !? */
union {
VoidPtr PVoid;
struct VertexStruct *PVertex;
struct PolygonStruct *PPolygon;
struct ObjectStruct *PObject;
} Data;
char Name[NAME_LEN];
Byte EntryType; /* Kind of pointer in union. */
Byte Used; /* TRUE if allready has been used (multi - referenced). */
} BinTree;
typedef struct FileDescription { /* Each data file loaded gets such struct. */
BinTree *VertexPointer, /* Pointers on the binary trees ... */
*PolygonPointer,
*ObjectPointer;
} FileDescription;
/* Use the following structure if linear list operations are to be performed */
/* on VertexStruct/PolygonStruct/ObjectStruct (Virtual functions...). */
typedef struct LinearListStruct {
struct LinearListStruct *Pnext;
} LinearListStruct;
typedef struct VertexStruct {
struct VertexStruct *Pnext;
float Coord[3]; /* The 3D coords. */
float Normal[3]; /* The 3D normal. */
Byte Transform;
Byte Internal; /* If edge is Internal (IRIT output). */
Byte HasNormal; /* If edge has a normal defined. */
} VertexStruct;
typedef struct PolygonStruct {
struct PolygonStruct *Pnext;
VertexStruct *PVertex; /* The polygon vertices. */
float Plane[4]; /* The Polygon plane equation. */
Byte PolyType; /* One of POLYGON, POLYLINE, POINTLIST. */
Byte HasPlane; /* If polygon has a plane defined. */
} PolygonStruct;
typedef struct ObjectStruct {
struct ObjectStruct *Pnext;
PolygonStruct *PPolygon; /* The objects polygons. */
int Color;
} ObjectStruct;
/* And function prototypes: */
FileDescription *GetDataFile(FILE *f);
void GetViewFile(FILE *f, int FileExists);
BinTree *GetBinTree(char *RecName, BinTree *Tree);
extern unsigned int _stklen = 32766; /* Increase default stack size. */
static int GlblToken = 0, /* Used by the parser, to unget token. */
GlblLineCount = 1, /* Used to locate errors in input file. */
GlblParserError = 0; /* Save last error number found. */
static char GlblStringToken[UNGET_STACK_SIZE][LINE_LEN];/* Save unget tokens.*/
static struct FileDescription *Descriptor;
char *Real2Str(double R);
static struct BinTree *AllocBinTree(int Entry, VoidPtr Data);
static void UnGetToken(char *StringToken);
static void GetStringToken(FILE *f, char *StringToken);
static int GetToken(FILE *f, char *StringToken);
static void GetVertexAttributes(VertexStruct *PVertex, FILE *f);
static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f);
static void GetObjectAttributes(ObjectStruct *PObject, FILE *f);
static void EliminateComments(FILE *f);
static void ParserError(int ErrNum, char *Msg);
static void InsertBinTree(BinTree **Tree, BinTree *PNewRecord);
static LinearListStruct *GetNameFromFD(char *Name, FileDescription *FD,
int EntryTypes);
static VoidPtr GetLinList(FILE *f, FileDescription *FD, int EntryTypes);
static char *MyMalloc(unsigned size);
static void MyExit(int ExitCode);
/*****************************************************************************
* *
*****************************************************************************/
void main(int argc, char **argv)
{
FILE *f = NULL;
if (argc == 2 && (f = fopen(argv[1], "rt")) != NULL)
GetDataFile(f);
else GetDataFile(stdin);
if (f) fclose(f);
MyExit(0);
printf("%lf", exp((double) argc));
}
/*****************************************************************************
* Dump out the new format (simpler, isnt it!?). *
*****************************************************************************/
void DumpOutObject(BinTree *T)
{
int i;
struct ObjectStruct *PObject = T -> Data.PObject;
struct PolygonStruct *PPolygon = PObject -> PPolygon;
struct VertexStruct *PVertex;
printf("[OBJECT [COLOR %d] %s\n", PObject -> Color, T -> Name);
while (PPolygon) {
for (i = 0, PVertex = PPolygon -> PVertex;
PVertex != NULL;
i++, PVertex = PVertex -> Pnext);
printf(" [%s", PPolygon -> PolyType == POLYLINE ? "POLYLINE" :
PPolygon -> PolyType == POLYGON ? "POLYGON" : "POINTLIST");
if (PPolygon -> HasPlane)
printf(" [PLANE %s %s %s %s]",
Real2Str(PPolygon -> Plane[0]),
Real2Str(PPolygon -> Plane[1]),
Real2Str(PPolygon -> Plane[2]),
Real2Str(PPolygon -> Plane[3]));
printf(" %d\n", i);
PVertex = PPolygon -> PVertex;
while (PVertex) {
printf("\t[");
if (PVertex -> Internal)
printf("[INTERNAL] ");
if (PVertex -> HasNormal)
printf("[NORMAL %s %s %s] ",
Real2Str(PVertex->Normal[0]),
Real2Str(PVertex->Normal[1]),
Real2Str(PVertex->Normal[2]));
printf("%s %s %s]\n",
Real2Str(PVertex->Coord[0]),
Real2Str(PVertex->Coord[1]),
Real2Str(PVertex->Coord[2]));
PVertex = PVertex -> Pnext;
}
printf(" ]\n");
PPolygon = PPolygon -> Pnext;
}
printf("] /* OBJECT %s */\n", T -> Name);
}
/*****************************************************************************
* Convert a real number into a string. *
*****************************************************************************/
char *Real2Str(double R)
{
static int i = 0;
static char Buffer[10][LINE_LEN];
int j, k;
sprintf(Buffer[i], "%-8.6lg", R);
for (k = 0; !isdigit(Buffer[i][k]) && k < LINE_LEN; k++);
if (k >= LINE_LEN) {
fprintf(stderr, "Conversion of real number failed.\n");
MyExit(3);
}
for (j = strlen(Buffer[i]) - 1; Buffer[i][j] == ' ' && j > k; j--);
if (strchr(Buffer[i], '.') != NULL)
for (; Buffer[i][j] == '0' && j > k; j--);
Buffer[i][j+1] = 0;
j = i;
i = (i + 1) % 10;
return Buffer[j];
}
/*****************************************************************************
* Routine to read the data from a given file and update the data structures *
* Descriptor (which returned) from it. *
* If MoreFlag is on then more printed staff will be given... *
*****************************************************************************/
FileDescription *GetDataFile(FILE *f)
{
int i;
char StringToken[LINE_LEN];
struct VertexStruct *PVertex;
struct PolygonStruct *PPolygon;
struct ObjectStruct *PObject;
struct BinTree *PBinTree;
GlblToken = 0;
Descriptor = (FileDescription *) MyMalloc(sizeof(FileDescription));
/* As all the trees are empty set the following: */
Descriptor -> VertexPointer =
Descriptor -> PolygonPointer =
Descriptor -> ObjectPointer = (BinTree *) NULL;
GlblLineCount = 1; /* Reset line counter. */
EliminateComments(f); /* Skip all comments including '['. */
while (!feof(f)) {
GlblParserError = 0; /* Reset errors. */
switch (GetToken(f, StringToken)) {
case TOKEN_VERTEX:
PVertex = (VertexStruct *) MyMalloc(sizeof(VertexStruct));
PVertex -> Transform = FALSE; /* Flag if vertex transformed. */
PVertex -> Internal = FALSE; /* Flag if vertex is internal. */
PVertex -> HasNormal = FALSE; /* Flag if vertex has normal. */
PBinTree = AllocBinTree(VERTEX_ENTRY, (VoidPtr) PVertex);
GetToken(f, PBinTree -> Name); /* Get the name. */
if (strlen(PBinTree -> Name) >= NAME_LEN)
ParserError(P_ERR_NAME_TOO_LONG, PBinTree -> Name);
/* The following handle the optional attributes in record. */
if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
GetVertexAttributes(PVertex, f); /* Get attributes. */
else UnGetToken(StringToken);
/* The following handles reading of 3 coord. of vertex. */
for (i=0; i<3 ;i++) {
GetToken(f, StringToken);
if (sscanf(StringToken, "%f", &PVertex -> Coord[i]) != 1)
ParserError(P_ERR_NUMBER_EXPECTED, StringToken);
}
if ((i=GetToken(f, StringToken)) != TOKEN_CLOSE_PAREN)
ParserError(P_ERR_CLOSE_PAREN_EXPECTED, StringToken);
if (!GlblParserError)
InsertBinTree(&Descriptor -> VertexPointer, PBinTree);
break;
case TOKEN_POLYGON:
PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
PPolygon -> PolyType = POLYGON;
PPolygon -> HasPlane = FALSE;
PBinTree = AllocBinTree(POLYGON_ENTRY, (VoidPtr) PPolygon);
GetToken(f, PBinTree -> Name); /* Get the name. */
if (strlen(PBinTree -> Name) >= NAME_LEN)
ParserError(P_ERR_NAME_TOO_LONG, PBinTree -> Name);
/* The following handle the optional attributes in record. */
if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
GetPolygonAttributes(PPolygon, f);
else UnGetToken(StringToken);
/* The following handles reading the members list. */
PPolygon -> PVertex = (VertexStruct *)
GetLinList(f, Descriptor, VERTEX_ENTRY);
if (!GlblParserError)
InsertBinTree(&Descriptor -> PolygonPointer, PBinTree);
break;
case TOKEN_POLYLINE:
PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
PPolygon -> PolyType = POLYLINE;
PPolygon -> HasPlane = FALSE;
PBinTree = AllocBinTree(POLYGON_ENTRY, (VoidPtr) PPolygon);
GetToken(f, PBinTree -> Name); /* Get the name. */
if (strlen(PBinTree -> Name) >= NAME_LEN)
ParserError(P_ERR_NAME_TOO_LONG, PBinTree -> Name);
/* The following handle the optional attributes in record. */
if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
GetPolygonAttributes(PPolygon, f);
else UnGetToken(StringToken);
/* The following handles reading the members list. */
PPolygon -> PVertex = (VertexStruct *)
GetLinList(f, Descriptor, VERTEX_ENTRY);
if (!GlblParserError)
InsertBinTree(&Descriptor -> PolygonPointer, PBinTree);
break;
case TOKEN_POINTLIST:
PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
PPolygon -> PolyType = POINTLIST;
PPolygon -> HasPlane = FALSE;
PBinTree = AllocBinTree(POLYGON_ENTRY, (VoidPtr) PPolygon);
GetToken(f, PBinTree -> Name); /* Get the name. */
if (strlen(PBinTree -> Name) >= NAME_LEN)
ParserError(P_ERR_NAME_TOO_LONG, PBinTree -> Name);
/* The following handle the optional attributes in record. */
if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
GetPolygonAttributes(PPolygon, f);
else UnGetToken(StringToken);
/* The following handles reading the members list. */
PPolygon -> PVertex = (VertexStruct *)
GetLinList(f, Descriptor, VERTEX_ENTRY);
if (!GlblParserError)
InsertBinTree(&Descriptor -> PolygonPointer, PBinTree);
break;
case TOKEN_OBJECT:
PObject = (ObjectStruct *) MyMalloc(sizeof(ObjectStruct));
PObject-> Color = 1;
PBinTree = AllocBinTree(OBJECT_ENTRY, (VoidPtr) PObject);
GetToken(f, PBinTree -> Name); /* Get the name. */
if (strlen(PBinTree -> Name) >= NAME_LEN) {
/* Although this may be considered an error, no one */
/* reference objects, so we can simply truncate it. */
PBinTree -> Name[NAME_LEN - 1] = 0;
}
/* The following handle the optional attributes in record. */
if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
GetObjectAttributes(PObject, f);
else UnGetToken(StringToken);
/* The following handles reading the polygon list. */
/* Note an object might be created from Polygons only. */
PObject -> PPolygon = (PolygonStruct *)
GetLinList(f, Descriptor, POLYGON_ENTRY);
if (!GlblParserError)
InsertBinTree(&Descriptor -> ObjectPointer, PBinTree);
DumpOutObject(PBinTree);
break;
default:
ParserError(P_ERR_UNDEF_EXPR_HEADER, StringToken);
break;
} /* Of switch. */
if (!feof(f)) EliminateComments(f); /* Skip comments including '['. */
} /* Of while !eof. */
return Descriptor;
}
/*****************************************************************************
* Routine to allocate one BinTree Item: *
*****************************************************************************/
static struct BinTree *AllocBinTree(int Entry, VoidPtr Data)
{
struct BinTree *PBinTree;
PBinTree = (BinTree *) MyMalloc(sizeof(BinTree));
PBinTree -> EntryType = Entry;
PBinTree -> Used = FALSE;
PBinTree -> Data.PVoid = Data;
PBinTree -> right = PBinTree -> left = (BinTree *) NULL;
return PBinTree;
}
/*****************************************************************************
* Routine to unget one token (on stack of UNGET_STACK_SIZE levels!) *
*****************************************************************************/
static void UnGetToken(char *StringToken)
{
if (GlblToken >= UNGET_STACK_SIZE) {
printf("Parser Internal stack overflow...\n");
MyExit(1);
}
strcpy(GlblStringToken[GlblToken], StringToken);
GlblToken++; /* GlblToken exists - Something in it (no overflow check). */
}
/*****************************************************************************
* Routine to get the next token out of the input file f. *
* Returns the next token found, as StringToken. *
* Note: StringToken must be allocated before calling this routine! *
*****************************************************************************/
static void GetStringToken(FILE *f, char *StringToken)
{
int len;
char c, *LocalStringToken;
if (GlblToken) { /* get first the unget token */
GlblToken--;
strcpy(StringToken, GlblStringToken[GlblToken]);
return;
}
/* skip white spaces: */
while ((!feof(f))
&& (((c = getc(f)) == ' ') || (c == '\t') || (c == '\n')))
if (c == '\n') GlblLineCount++; /* Count the lines. */
LocalStringToken = StringToken;
if (c == '[') /* Its a token by itself so return it. */
*LocalStringToken++ = c; /* Copy the token into string. */
else {
if (!feof(f))
do *LocalStringToken++ = c; /* Copy the token into string. */
while ((!feof(f)) &&
((c = getc(f)) != ' ') && (c != '\t') && (c != '\n'));
if (c == '\n') ungetc(c, f); /* Save it to be counted next time. */
}
*LocalStringToken = NULL; /* Put eos. */
/* The following handles the spacial case were we have XXXX] - we must */
/* split it into two token XXXX and ], UnGetToken(']') and return XXXX: */
if ((StringToken[len = strlen(StringToken)-1] == ']') && (len > 0)) {
/* Return CloseParan */
UnGetToken(&StringToken[len]); /* Save next token. */
StringToken[len] = NULL; /* Set end of string on "]". */
}
}
/*****************************************************************************
* Routine to get the next token out of the input file f as token number. *
* Returns the next token number found, with numeric result in NumericToken *
* if TokenType is TOKEN_NUMBER. *
* Note: StringToken must be allocated before calling this routine! *
*****************************************************************************/
static int GetToken(FILE *f, char *StringToken)
{
GetStringToken(f, StringToken);
if (feof(f)) return TOKEN_EOF;
if (!strcmp(StringToken, "[")) return TOKEN_OPEN_PAREN;
if (!strcmp(StringToken, "]")) return TOKEN_CLOSE_PAREN;
if (!strcmp(StringToken, "VERTEX")) return TOKEN_VERTEX;
if (!strcmp(StringToken, "POLYGON")) return TOKEN_POLYGON;
if (!strcmp(StringToken, "POLYLINE")) return TOKEN_POLYLINE;
if (!strcmp(StringToken, "POINTLIST")) return TOKEN_POINTLIST;
if (!strcmp(StringToken, "OBJECT")) return TOKEN_OBJECT;
if (!strcmp(StringToken, "COLOR")) return TOKEN_COLOR;
if (!strcmp(StringToken, "INTERNAL")) return TOKEN_INTERNAL;
if (!strcmp(StringToken, "NORMAL")) return TOKEN_NORMAL;
if (!strcmp(StringToken, "PLANE")) return TOKEN_PLANE;
if (!strcmp(StringToken, "CBEZIER")) return TOKEN_CBEZIER;
if (!strcmp(StringToken, "SBEZIER")) return TOKEN_SBEZIER;
if (!strcmp(StringToken, "CNURB")) return TOKEN_CNURB;
if (!strcmp(StringToken, "SNURB")) return TOKEN_SNURB;
return TOKEN_OTHER; /* Must be number or name. */
}
/*****************************************************************************
* Routine to read from input file f the following [ATTR ...] [ATTR ...]. *
* Note the '[' was allready read. *
* Current supported attributes: [INTERNAL] - internal edge (IRIT output) *
*****************************************************************************/
static void GetVertexAttributes(VertexStruct *PVertex, FILE *f)
{
int i;
char StringToken[LINE_LEN];
do {
switch (GetToken(f, StringToken)) {
case TOKEN_INTERNAL:
PVertex -> Internal = TRUE;
if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
ParserError(P_ERR_CLOSE_PAREN_EXPECTED, StringToken);
break;
case TOKEN_NORMAL:
PVertex -> HasNormal = TRUE;
/* The following handles reading of 3 coord. of normal. */
for (i=0; i<3 ;i++) {
GetToken(f, StringToken);
if (sscanf(StringToken, "%f", &PVertex -> Normal[i]) != 1)
ParserError(P_ERR_NUMBER_EXPECTED, StringToken);
}
if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
ParserError(P_ERR_CLOSE_PAREN_EXPECTED, StringToken);
break;
default: /* Ignore this option! */
while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
break;
}
}
while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
UnGetToken(StringToken);
}
/*****************************************************************************
* Routine to read from input file f the following [ATTR ...] [ATTR ...]. *
* Note the '[' was allready read. *
* Current supported attributes: None *
*****************************************************************************/
static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f)
{
int i;
char StringToken[LINE_LEN];
do {
switch (GetToken(f, StringToken)) {
case TOKEN_PLANE:
PPolygon -> HasPlane = TRUE;
/* The following handles reading of 4 coord. of plane eqn.. */
for (i=0; i<4 ;i++) {
GetToken(f, StringToken);
if (sscanf(StringToken, "%f", &PPolygon -> Plane[i]) != 1)
ParserError(P_ERR_NUMBER_EXPECTED, StringToken);
}
if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
ParserError(P_ERR_CLOSE_PAREN_EXPECTED, StringToken);
break;
default:
while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
break;
}
}
while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
UnGetToken(StringToken);
}
/*****************************************************************************
* Routine to read from input file f the following [ATTR ...] [ATTR ...]. *
* Note the '[' was allready read. *
* Current supported attributes: [COLOR C] - set color. *
*****************************************************************************/
static void GetObjectAttributes(ObjectStruct *PObject, FILE *f)
{
int i;
char StringToken[LINE_LEN];
do {
switch (GetToken(f, StringToken)) {
case TOKEN_COLOR:
GetToken(f, StringToken);
if (sscanf(StringToken, "%d", &i) != 1)
ParserError(P_ERR_NUMBER_EXPECTED, StringToken);
if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
ParserError(P_ERR_CLOSE_PAREN_EXPECTED, StringToken);
PObject -> Color = i;
break;
default:
while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
break;
}
}
while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
UnGetToken(StringToken);
}
/*****************************************************************************
* Routine to read the input tokens up to a '[' token - skip comments. *
* Note the routine reads the '[' token, so next is the expression itself. *
*****************************************************************************/
static void EliminateComments(FILE *f)
{
char StringToken[LINE_LEN];
while ((!feof(f)) && (GetToken(f, StringToken) != TOKEN_OPEN_PAREN));
}
/*****************************************************************************
* Routine to print pasring error according to ErrNum and set GlblParserError.*
*****************************************************************************/
static void ParserError(int ErrNum, char *Msg)
{
GlblParserError = TRUE;
printf("Error in line %3d : ", GlblLineCount);
switch (ErrNum) {
case P_ERR_NUMBER_EXPECTED:
printf("Numeric data expected, ");
break;
case P_ERR_OPEN_PAREN_EXPECTED:
printf("[ expected, ");
break;
case P_ERR_CLOSE_PAREN_EXPECTED:
printf("] expected, ");
break;
case P_ERR_LIST_COMP_UNDEF:
printf("List component undefined - ");
break;
case P_ERR_UNDEF_EXPR_HEADER:
printf("Undefined expression header - ");
break;
case P_ERR_NAME_TOO_LONG:
printf("Object Name too long (Max %d) - ", NAME_LEN - 1);
break;
case P_ERR_PT_TYPE_EXPECTED:
printf("Point type expected, ");
break;
default:
printf("Unknown error, ");
break;
}
printf("found %s.\n", Msg);
}
/*****************************************************************************
* Routine to insert new element into a binary tree. If the element already *
* exists then the new one replace it. *
*****************************************************************************/
static void InsertBinTree(BinTree **Tree, BinTree *PNewRecord)
{
int Comparison;
BinTree *PBin;
if (*Tree == (BinTree *) NULL) /* Only might happen if the tree empty. */
*Tree = PNewRecord;
else { /* Search for the new place to put it. */
/* Test for Match - if so replace old by new: */
if ((Comparison = strcmp((*Tree) -> Name, PNewRecord -> Name)) == 0) {
PBin = *Tree;
*Tree = PNewRecord; /* Replace. */
switch (PBin -> EntryType) { /* Free the data area (union). */
case VERTEX_ENTRY:
free((char *) PBin -> Data.PVertex);
break;
case POLYGON_ENTRY:
free((char *) PBin -> Data.PPolygon);
break;
case OBJECT_ENTRY:
free((char *) PBin -> Data.PObject);
break;
default:
/* Should not be, unless was not updated here... */
break;
}
free((char *) PBin);
}
else if (Comparison > 0) /* Go to right side - its bigger. */
if ((*Tree) -> right != (BinTree *) NULL) /* Only if exist. */
InsertBinTree(&((*Tree) -> right), PNewRecord);
else (*Tree) -> right = PNewRecord; /* Put record in place. */
else if ((*Tree) -> left != (BinTree *) NULL) /* Only if exist. */
InsertBinTree(&((*Tree) -> left), PNewRecord);/*Smaller. */
else (*Tree) -> left = PNewRecord; /* Put record in place. */
}
}
/*****************************************************************************
* Routine to Get an element from binary tree. If the element is found a *
* pointer to it BinTree record is return, NULL else... *
*****************************************************************************/
BinTree *GetBinTree(char *RecName, BinTree *Tree)
{
int Comparison;
/* If the tree is empty - not found, return NULL: */
if (Tree == (BinTree *) NULL) return (BinTree *) NULL;
/* Test for Match - if so return that record: */
if ((Comparison = strcmp(Tree -> Name, RecName)) == 0)
return Tree; /* Found it - so return it ... */
else if (Comparison > 0)
return GetBinTree(RecName, Tree -> right);
else return GetBinTree(RecName, Tree -> left);
}
/*****************************************************************************
* Routine to search for Name in the trees, allowed by EntryTypes, of the *
* file descrition FD. NULL returned if not found. The order of search is: *
* VERTEX , POLYGON , OBJECT. *
* Once found, if was already used (multi-reference) it is copied fresh. *
*****************************************************************************/
static LinearListStruct *GetNameFromFD(char *Name, FileDescription *FD,
int EntryTypes)
{
BinTree *PBin;
VertexStruct *PVertex;
PolygonStruct *PPolygon;
ObjectStruct *PObject;
if (EntryTypes & VERTEX_ENTRY) { /* Check in vertices tree. */
if ((PBin = GetBinTree(Name, FD -> VertexPointer)) != NULL) {
if (PBin -> Used) {
PVertex = (VertexStruct *) MyMalloc(sizeof(VertexStruct));
GEN_COPY(PVertex, PBin -> Data.PVertex, sizeof(VertexStruct));
return (LinearListStruct *) PVertex;
}
else {
PBin -> Used = TRUE;
return (LinearListStruct *) PBin -> Data.PVertex;
}
}
}
if (EntryTypes & POLYGON_ENTRY) { /* Check in polygon tree. */
if ((PBin = GetBinTree(Name, FD -> PolygonPointer)) != NULL) {
if (PBin -> Used) {
PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
GEN_COPY(PPolygon, PBin -> Data.PPolygon, sizeof(PolygonStruct));
return (LinearListStruct *) PPolygon;
}
else {
PBin -> Used = TRUE;
return (LinearListStruct *) PBin -> Data.PPolygon;
}
}
}
if (EntryTypes & OBJECT_ENTRY) { /* Check in object tree. */
if ((PBin = GetBinTree(Name, FD -> ObjectPointer)) != NULL) {
if (PBin -> Used) {
PObject = (ObjectStruct *) MyMalloc(sizeof(ObjectStruct));
GEN_COPY(PObject, PBin -> Data.PObject, sizeof(ObjectStruct));
return (LinearListStruct *) PObject;
}
else {
PBin -> Used = TRUE;
return (LinearListStruct *) PBin -> Data.PObject;
}
}
}
return NULL; /* Not found. */
}
/*****************************************************************************
* Routine to get linear list of names from file f until ']' is detected. *
* search for that names in file description FD unter the trees allowed *
* according to EntryTypes (1 bit per entry, see ?????Entry is parser.h). *
* Create a linear list of pointers to them. Return that linear list. *
*****************************************************************************/
static VoidPtr GetLinList(FILE *f, FileDescription *FD, int EntryTypes)
{
char StringToken[LINE_LEN];
struct LinearListStruct *PLinHead = NULL, *PLinTail = NULL, *PItem;
while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN) {
if ((PItem = GetNameFromFD(StringToken, FD, EntryTypes)) == NULL) {
ParserError(P_ERR_LIST_COMP_UNDEF, StringToken);/* Record undef. */
continue; /* To next component to search for. */
}
if (PLinHead == NULL) /* Its first record. */
PLinHead = PLinTail = PItem;
else { /* Its record in the middle. */
PLinTail -> Pnext = PItem;
PLinTail = PItem;
}
}
if (PLinTail != NULL) PLinTail -> Pnext = NULL; /* Mark end of list. */
return (VoidPtr) PLinHead;
}
/*****************************************************************************
* My Routine to allocate dynamic memory. All program requests must call this *
* routine (no direct call to malloc). Dies if no memory. *
*****************************************************************************/
static char *MyMalloc(unsigned size)
{
char *p;
if ((p = malloc(size)) != NULL) return p;
printf("Not enough memory, exit\n");
MyExit(2);
return NULL; /* Make warnings silent. */
}
/*****************************************************************************
* MyExit routine. Note it might call to CloseGraph without calling *
* InitGraph(), or call MouseClose() without MouseInit() etc. and it is the *
* responsibility of the individual modules to do nothing in these cases. *
*****************************************************************************/
static void MyExit(int ExitCode)
{
exit(ExitCode);
}