/***************************************************************************** * Generic parser for the "Irit" solid modeller. * ****************************************************************************** * (C) Gershon Elber, Technion, Israel Institute of Technology * ****************************************************************************** * Written by: Gershon Elber Ver 0.2, Sep. 1991 * *****************************************************************************/ #ifdef USE_VARARGS #include #else #include #endif /* USE_VARARGS */ #include #include #include #include #include #include "irit_sm.h" #include "prsr_loc.h" #include "allocate.h" #include "attribut.h" #ifdef __WINNT__ #include #include #endif /* __WINNT__ */ #define ZERO_NUM_IRIT_EPS 1e-13 STATIC_DATA char GlblTokenError[LINE_LEN_LONG]; /* Last token error was found. */ STATIC_DATA IPPrintFuncType IPPrintFunc = NULL; GLOBAL_DATA jmp_buf _IPLongJumpBuffer; /* Used in error traping. */ GLOBAL_DATA int _IPReadOneObject = FALSE, /* If only one object is to be read. */ _IPFilterDegeneracies = TRUE; GLOBAL_DATA IPErrType _IPGlblParserError = IP_NO_ERR; /* Last err # found. */ GLOBAL_DATA char *_IPGlblFloatFormat = "%-16.14lg"; static void IPPutAttributes(int Handler, IPAttributeStruct *Attr, int Indent); static void IPPutAllObjects(IPObjectStruct *PObj, int Handler, int Indent); /***************************************************************************** * DESCRIPTION: M * Routine to abort parsing operation and save error reported. M * See also function IPParseError. M * * * PARAMETERS: M * ErrNum: Type of error that had occured. M * Msg: A message to accompany the error number. M * * * RETURN VALUE: M * void M * * * KEYWORDS: M * _IPParserAbort, error handling, files, parser M *****************************************************************************/ void _IPParserAbort(IPErrType ErrNum, char *Msg) { _IPGlblParserError = ErrNum; strcpy(GlblTokenError, Msg); /* Keep the message in safe place... */ longjmp(_IPLongJumpBuffer, 1); /* Jump to... */ } /***************************************************************************** * DESCRIPTION: M * Returns TRUE if error has happend since last call to this function during M * data read or write, FALSE otherwise. M * If error, then ErrorMsg is updated to point on static str describing it. M * * * PARAMETERS: M * LineNum: Line number of error, in file/stream. M * ErrorMsg: To be updated with latest error to have happened in parser. M * * * RETURN VALUE: M * int: TRUE if error occured since last call, FALSE otherwise. M * * * KEYWORDS: M * IPParseError, error handling, files, parser M *****************************************************************************/ int IPParseError(int LineNum, char **ErrorMsg) { IPErrType Temp; char TempCopy[LINE_LEN_LONG]; if ((Temp = _IPGlblParserError) == IP_NO_ERR) return FALSE; strcpy(TempCopy, GlblTokenError); _IPGlblParserError = IP_NO_ERR; switch (Temp) { case IP_ERR_NUMBER_EXPECTED: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Numeric data expected - found %s"), LineNum, TempCopy); break; case IP_ERR_OPEN_PAREN_EXPECTED: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: '[' expected - found '%s'"), LineNum, TempCopy); break; case IP_ERR_CLOSE_PAREN_EXPECTED: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: ']' expected - found '%s'"), LineNum, TempCopy); break; case IP_ERR_LIST_COMP_UNDEF: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Undefined list element - \"%s\""), LineNum, TempCopy); break; case IP_ERR_UNDEF_EXPR_HEADER: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Undefined TOKEN - \"%s\""), LineNum, TempCopy); break; case IP_ERR_PT_TYPE_EXPECTED: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Point type expected"), LineNum); break; case IP_ERR_OBJECT_EMPTY: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Empty object found"), LineNum); break; case IP_ERR_FILE_EMPTY: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Empty file found"), LineNum); break; case IP_ERR_MIXED_TYPES: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Mixed data types in same object"), LineNum); break; case IP_ERR_STR_NOT_IN_QUOTES: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: String not in quotes (%s)"), LineNum, TempCopy); break; case IP_ERR_STR_TOO_LONG: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: String too long:\"%s\""), LineNum, TempCopy); break; case IP_ERR_OBJECT_EXPECTED: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: 'OBJECT' expected, found '%s'"), LineNum, TempCopy); break; case IP_ERR_CAGD_LIB_ERR: case IP_ERR_TRIM_LIB_ERR: case IP_ERR_TRIV_LIB_ERR: case IP_ERR_TRNG_LIB_ERR: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: %s"), LineNum, TempCopy); break; case IP_ERR_STACK_OVERFLOW: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Parser Stack overflow"), LineNum); break; case IP_ERR_DEGEN_POLYGON: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Degenerate polygon"), LineNum); break; case IP_ERR_DEGEN_NORMAL: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Degenerate normal"), LineNum); break; case IP_ERR_SOCKET_BROKEN: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Socket connection is broken"), LineNum); break; case IP_ERR_SOCKET_TIME_OUT: sprintf(GlblTokenError, IRIT_EXP_STR("Line %d: Socket connection is broken"), LineNum); break; case IP_ERR_BIN_IN_TEXT: sprintf(GlblTokenError, IRIT_EXP_STR("Binary information in text file - %s"), TempCopy); break; case IP_ERR_BIN_UNDEF_OBJ: sprintf(GlblTokenError, IRIT_EXP_STR("Binary stream: Undefined object")); break; case IP_ERR_BIN_WRONG_SIZE: sprintf(GlblTokenError, IRIT_EXP_STR("Binary object detected with wrong sizes")); break; default: sprintf(GlblTokenError, IRIT_EXP_STR("parsing of data file at line %d - undefined error"), LineNum); break; } *ErrorMsg = GlblTokenError; return TRUE; } /***************************************************************************** * DESCRIPTION: M * Routine to print the data from given object into stdout. M * * * PARAMETERS: M * PObj: To be put out to stdout. M * IsBinary: Is this a binary file we should dump? M * * * RETURN VALUE: M * void M * * * KEYWORDS: M * IPStdoutObject, files M *****************************************************************************/ void IPStdoutObject(IPObjectStruct *PObj, int IsBinary) { IPPutObjectToFile(stdout, PObj, IsBinary); } /***************************************************************************** * DESCRIPTION: M * Routine to print the data from given object into stderr. M * * * PARAMETERS: M * PObj: To be put out to stderr. M * * * RETURN VALUE: M * void M * * * KEYWORDS: M * IPStderrObject, files M *****************************************************************************/ void IPStderrObject(IPObjectStruct *PObj) { IPPutObjectToFile(stderr, PObj, FALSE); } /***************************************************************************** * DESCRIPTION: M * Routine to print the data from given object into given file handle. M * See function IPSetPrintFunc, IPSetFloatFormat. M * * * PARAMETERS: M * f: Output stream file handle. M * PObj: Object to put on output stream. M * IsBinary: Is this a binary file we should dump? M * * * RETURN VALUE: M * void M * * * KEYWORDS: M * IPPutObjectToFile, files M *****************************************************************************/ void IPPutObjectToFile(FILE *f, IPObjectStruct *PObj, int IsBinary) { int Handler = -1; /* If the following gain control and is non zero - its from error! */ if (setjmp(_IPLongJumpBuffer) != 0) { IPCloseStream(Handler, FALSE); return; } Handler = IPOpenStreamFromFile(f, FALSE, IsBinary, FALSE, FALSE); if (_IPStream[Handler].FileType == IP_FILE_BINARY) IPPutBinObject(Handler, PObj); #ifdef IPC_BIN_COMPRESSION else if (_IPStream[Handler].FileType == IP_FILE_COMPRESSED) IpcCompressObj(Handler, PObj); #endif /* IPC_BIN_COMPRESSION */ else IPPutAllObjects(PObj, Handler, 0); IPCloseStream(Handler, FALSE); } /***************************************************************************** * DESCRIPTION: M * Routine to print the data from given object into given file FileName. M * If FileName is NULL or empty, print using IPPrintFunc. M * See function IPSetPrintFunc, IPSetFloatFormat. M * * * PARAMETERS: M * f: Output stream. M * PObj: Object to put on output stream. M * Indent: File indentation (always a text file). M * * * RETURN VALUE: M * void M * * * KEYWORDS: M * IPPutObjectToFile2, files M *****************************************************************************/ void IPPutObjectToFile2(FILE *f, IPObjectStruct *PObj, int Indent) { int Handler = -1; /* If the following gain control and is non zero - its from error! */ if (setjmp(_IPLongJumpBuffer) != 0) { IPCloseStream(Handler, FALSE); return; } Handler = IPOpenStreamFromFile(f, FALSE, FALSE, FALSE, FALSE); IPPutAllObjects(PObj, Handler, Indent); IPCloseStream(Handler, FALSE); } /***************************************************************************** * DESCRIPTION: M * Routine to print the data from given object into given file designated via M * Handler. M * * * PARAMETERS: M * Handler: A handler to the open stream. M * PObj: Object to put on output stream. M * * * RETURN VALUE: M * void M * * * SEE ALSO: M * IPSetPrintFunc, IPSetFloatFormat, IPPrintFunc _IPFprintf M * * * KEYWORDS: M * IPPutObjectToHandler, files M *****************************************************************************/ void IPPutObjectToHandler(int Handler, IPObjectStruct *PObj) { switch (_IPStream[Handler].Format) { case IP_VRML_FILE: IPPutVrmlObject(Handler, PObj, 0); break; case IP_IDAT_FILE: default: if (_IPStream[Handler].FileType == IP_FILE_BINARY) IPPutBinObject(Handler, PObj); #ifdef IPC_BIN_COMPRESSION else if (_IPStream[Handler].FileType == IP_FILE_COMPRESSED) IpcCompressObj(Handler, PObj); #endif /* IPC_BIN_COMPRESSION */ else IPPutAllObjects(PObj, Handler, 0); break; } } /***************************************************************************** * DESCRIPTION: * * Routine to print out the data from given object. * * * * PARAMETERS: * * PObj: Object to put out. * * Handler: A handler to the open stream. * * Indent: Indentation to put object at. * * * * RETURN VALUE: * * void * *****************************************************************************/ static void IPPutAllObjects(IPObjectStruct *PObj, int Handler, int Indent) { int i, IsRational, NumCoords; char Str[LINE_LEN_LONG], *ErrStr = NULL; CagdRType *Coords; IPObjectStruct *PObjTmp; IPPolygonStruct *PPolygon; IPVertexStruct *PVertex; IPAttributeStruct *Attr = AttrTraceAttributes(PObj -> Attr, PObj -> Attr); if (Attr) { _IPFprintf(Handler, Indent, "[OBJECT "); IPPutAttributes(Handler, Attr, Indent); _IPFprintf(Handler, 0, "%s\n", PObj -> ObjName != NULL && strlen(PObj -> ObjName) ? PObj -> ObjName : "NONE"); } else { _IPFprintf(Handler, Indent, "[OBJECT %s\n", PObj -> ObjName != NULL && strlen(PObj -> ObjName) ? PObj -> ObjName : "NONE"); } Indent += 4; switch (PObj -> ObjType) { case IP_OBJ_POLY: for (PPolygon = PObj -> U.Pl; PPolygon != NULL; PPolygon = PPolygon -> Pnext) { if (PPolygon -> PVertex == NULL) continue; if (IP_IS_POLYLINE_OBJ(PObj)) _IPFprintf(Handler, Indent, "[POLYLINE "); else if (IP_IS_POINTLIST_OBJ(PObj)) _IPFprintf(Handler, Indent, "[POINTLIST "); else { /* Make sure it has a valid plane normal. */ if (PT_APX_EQ_ZERO_EPS(PPolygon -> Plane, IRIT_UEPS)) { if (!IPUpdatePolyPlane(PPolygon)) { if (_IPFilterDegeneracies) continue; else { /* Default to plane Z = 0. */ PLANE_RESET(PPolygon -> Plane); PPolygon -> Plane[2] = 1.0; } } } _IPFprintf(Handler, Indent, "[%s [PLANE %s %s %s %s] ", IP_IS_POLYSTRIP_OBJ(PObj) ? "POLYSTRIP" : "POLYGON", _IPReal2Str(PPolygon -> Plane[0]), _IPReal2Str(PPolygon -> Plane[1]), _IPReal2Str(PPolygon -> Plane[2]), _IPReal2Str(PPolygon -> Plane[3])); } IPPutAttributes(Handler, PPolygon -> Attr, Indent); for (PVertex = PPolygon -> PVertex -> Pnext, i = 1; PVertex != PPolygon -> PVertex && PVertex != NULL; PVertex = PVertex -> Pnext, i++); _IPFprintf(Handler, Indent + 4, "%d\n", i); PVertex = PPolygon -> PVertex; do { /* Assume at least one edge in polygon! */ _IPFprintf(Handler, Indent + 4, "["); IPPutAttributes(Handler, PVertex -> Attr, Indent); if (IP_IS_POLYLINE_OBJ(PObj) || ((IP_IS_POLYGON_OBJ(PObj) || IP_IS_POLYSTRIP_OBJ(PObj)) && (PT_APX_EQ(PPolygon -> Plane, PVertex -> Normal) || PT_APX_EQ_ZERO_EPS(PVertex -> Normal, IRIT_UEPS)))) _IPFprintf(Handler, 0, "%s%s %s %s]\n", IP_IS_INTERNAL_VRTX(PVertex) ? "[INTERNAL] " : "", _IPReal2Str(PVertex -> Coord[0]), _IPReal2Str(PVertex -> Coord[1]), _IPReal2Str(PVertex -> Coord[2])); else if (IP_IS_POINTLIST_OBJ(PObj)) _IPFprintf(Handler, 0, "%s %s %s]\n", _IPReal2Str(PVertex -> Coord[0]), _IPReal2Str(PVertex -> Coord[1]), _IPReal2Str(PVertex -> Coord[2])); else _IPFprintf(Handler, 0, "%s[NORMAL %s %s %s] %s %s %s]\n", IP_IS_INTERNAL_VRTX(PVertex) ? "[INTERNAL] " : "", _IPReal2Str(PVertex -> Normal[0]), _IPReal2Str(PVertex -> Normal[1]), _IPReal2Str(PVertex -> Normal[2]), _IPReal2Str(PVertex -> Coord[0]), _IPReal2Str(PVertex -> Coord[1]), _IPReal2Str(PVertex -> Coord[2])); PVertex = PVertex -> Pnext; } while (PVertex != PPolygon -> PVertex && PVertex != NULL); _IPFprintf(Handler, Indent, "]\n"); /* Close the polygon. */ } break; case IP_OBJ_NUMERIC: _IPFprintf(Handler, Indent, "[NUMBER %s]\n", _IPReal2Str(PObj -> U.R)); break; case IP_OBJ_POINT: _IPFprintf(Handler, Indent, "[POINT %s %s %s]\n", _IPReal2Str(PObj -> U.Pt[0]), _IPReal2Str(PObj -> U.Pt[1]), _IPReal2Str(PObj -> U.Pt[2])); break; case IP_OBJ_VECTOR: _IPFprintf(Handler, Indent, "[VECTOR %s %s %s]\n", _IPReal2Str(PObj -> U.Vec[0]), _IPReal2Str(PObj -> U.Vec[1]), _IPReal2Str(PObj -> U.Vec[2])); break; case IP_OBJ_PLANE: _IPFprintf(Handler, Indent, "[PLANE %s %s %s %s]\n", _IPReal2Str(PObj -> U.Plane[0]), _IPReal2Str(PObj -> U.Plane[1]), _IPReal2Str(PObj -> U.Plane[2]), _IPReal2Str(PObj -> U.Plane[3])); break; case IP_OBJ_CTLPT: Coords = PObj -> U.CtlPt.Coords; IsRational = CAGD_IS_RATIONAL_PT(PObj -> U.CtlPt.PtType); NumCoords = CAGD_NUM_OF_PT_COORD(PObj -> U.CtlPt.PtType); sprintf(Str, "[CTLPT %c%d %s", IsRational ? 'P' : 'E', NumCoords, IsRational ? _IPReal2Str(Coords[0]) : ""); for (i = 1; i <= NumCoords; i++) { strcat(Str, " "); strcat(Str, _IPReal2Str(Coords[i])); } strcat(Str,"]\n"); _IPFprintf(Handler, Indent, Str); break; case IP_OBJ_MATRIX: _IPFprintf(Handler, Indent, "[MATRIX\n"); for (i = 0; i < 4; i++) _IPFprintf(Handler, Indent + 8, "%s %s %s %s%s\n", _IPReal2Str((*PObj -> U.Mat)[i][0]), _IPReal2Str((*PObj -> U.Mat)[i][1]), _IPReal2Str((*PObj -> U.Mat)[i][2]), _IPReal2Str((*PObj -> U.Mat)[i][3]), i == 3 ? "]" : ""); break; case IP_OBJ_INSTANCE: _IPFprintf(Handler, Indent, "[INSTANCE %s\n", PObj -> U.Instance -> Name); for (i = 0; i < 4; i++) _IPFprintf(Handler, Indent + 8, "%s %s %s %s%s\n", _IPReal2Str(PObj -> U.Instance -> Mat[i][0]), _IPReal2Str(PObj -> U.Instance -> Mat[i][1]), _IPReal2Str(PObj -> U.Instance -> Mat[i][2]), _IPReal2Str(PObj -> U.Instance -> Mat[i][3]), i == 3 ? "]" : ""); break; case IP_OBJ_STRING: _IPFprintf(Handler, Indent, "[STRING \"%s\"]\n", PObj -> U.Str); break; case IP_OBJ_LIST_OBJ: for (i = 0; (PObjTmp = IPListObjectGet(PObj, i)) != NULL; i++) { if (PObjTmp == PObj) IPFatalError("A list containing itself detected.\n"); else IPPutAllObjects(PObjTmp, Handler, Indent); } break; case IP_OBJ_CURVE: CagdCrvWriteToFile2(PObj -> U.Crvs, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr); break; case IP_OBJ_SURFACE: CagdSrfWriteToFile2(PObj -> U.Srfs, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr); break; case IP_OBJ_TRIMSRF: TrimWriteTrimmedSrfToFile2(PObj -> U.TrimSrfs, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_TRIM_LIB_ERR, ErrStr); break; case IP_OBJ_TRIVAR: TrivTVWriteToFile2(PObj -> U.Trivars, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_TRIV_LIB_ERR, ErrStr); break; case IP_OBJ_TRISRF: TrngTriSrfWriteToFile2(PObj -> U.TriSrfs, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_TRNG_LIB_ERR, ErrStr); break; case IP_OBJ_MODEL: MdlWriteModelToFile2(PObj -> U.Mdls, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_MDL_LIB_ERR, ErrStr); break; case IP_OBJ_MULTIVAR: MvarMVWriteToFile2(PObj -> U.MultiVars, Handler, Indent, NULL, &ErrStr); if (ErrStr != NULL) _IPParserAbort(IP_ERR_MVAR_LIB_ERR, ErrStr); break; default: IPFatalError("Attempt to print undefine object type."); break; } Indent -= 4; _IPFprintf(Handler, Indent, "]\n"); /* Close the object. */ } /***************************************************************************** * DESCRIPTION: M * Same as fprintf but with indentation. M * * * PARAMETERS: M * Handler: A handler to the open stream. M * Indent: All printing will start at this column. M * va_alist: Do "man stdarg" M * * * RETURN VALUE: M * void M * * * SEE ALSO: M * IPSetPrintFunc, IPSetFloatFormat, IPPrintFunc M * * * KEYWORDS: M * _IPFprintf, files M *****************************************************************************/ #ifdef USE_VARARGS void _IPFprintf(int Handler, int Indent, char *va_alist, ...) { char *Format, Line[LINE_LEN_VLONG]; int i; va_list ArgPtr; va_start(ArgPtr); Format = va_arg(ArgPtr, char *); #else void _IPFprintf(int Handler, int Indent, char *Format, ...) { char Line[LINE_LEN_VLONG]; int i; va_list ArgPtr; va_start(ArgPtr, Format); #endif /* USE_VARARGS */ if (IPPrintFunc != NULL || _IPStream[Handler].f != NULL) { for (i = 0; Indent >= 8; i++, Indent -= 8) Line[i] = '\t'; while (Indent--) Line[i++] = ' '; vsprintf(&Line[i], Format, ArgPtr); if (IPPrintFunc != NULL) IPPrintFunc(Line); else fprintf(_IPStream[Handler].f, Line); } else { /* _IPStream[Handler].f == NULL and it is a socket connction. */ /* No need for indentation if writing to a socket. */ vsprintf(Line, Format, ArgPtr); IPSocWriteLine(Handler, Line, (int) strlen(Line)); } va_end(ArgPtr); } /***************************************************************************** * DESCRIPTION: * * Routine to print the attributes of given attribute list. * * * * PARAMETERS: * * Handler: A handler to the open stream. * * Attr: Attributes to put out. * * Indent: Indentation to put attributes at. * * * * RETURN VALUE: * * void * *****************************************************************************/ static void IPPutAttributes(int Handler, IPAttributeStruct *Attr, int Indent) { int Count = 0; Attr = AttrTraceAttributes(Attr, Attr); while (Attr) { if (Attr -> Type == IP_ATTR_OBJ) { _IPFprintf(Handler, 0, "\n"); _IPFprintf(Handler, Indent + 4, "[%s\n", _AttrGetAttribName(Attr)); IPPutAllObjects(Attr -> U.PObj, Handler, Indent + 8); _IPFprintf(Handler, Indent + 4, "]\n"); _IPFprintf(Handler, Indent + 4, ""); } else _IPFprintf(Handler, 0, "%s ", Attr2String(Attr, TRUE)); Attr = AttrTraceAttributes(Attr, NULL); if (++Count >= 2 && Attr != NULL) { /* Allow two attributes at most per line. */ _IPFprintf(Handler, 0, "\n"); _IPFprintf(Handler, Indent + 4, ""); Count = 0; } } } /***************************************************************************** * DESCRIPTION: * * Convert a real number into a string. * * The routine maintains six different buffers simultanuously so up to six * * consecutive calls can be issued from same printf and still have valid * * strings. * * * * PARAMETERS: * * R: A real number to convert to a string. * * * * RETURN VALUE: * * char *: A string representing R allocated statically. * *****************************************************************************/ char *_IPReal2Str(RealType R) { STATIC_DATA int j, k, i = 0; STATIC_DATA char Buffer[6][LINE_LEN]; if (FABS(R) < ZERO_NUM_IRIT_EPS) R = 0.0; /* Round off very small numbers. */ sprintf(Buffer[i], _IPGlblFloatFormat, R); for (k = 0; !isdigit(Buffer[i][k]) && k < LINE_LEN; k++); if (k >= LINE_LEN) { fprintf(stderr, IRIT_EXP_STR("Warning: Conversion of real number (%f) failed, zero coerced.\n"), R); R = 0.0; } for (j = (int) strlen(Buffer[i]) - 1; Buffer[i][j] == ' ' && j > k; j--); if (strchr(Buffer[i], '.') != NULL && strchr(Buffer[i], 'e') == NULL && strchr(Buffer[i], 'E') == NULL) for (; Buffer[i][j] == '0' && j > k; j--); Buffer[i][j + 1] = 0; j = i; i = (i + 1) % 6; return Buffer[j]; } /***************************************************************************** * DESCRIPTION: M * Convert a real number into a string. M * The routine maintains six different buffers simultanuously so up to six M * consecutive calls can be issued from same printf and still have valid M * strings. M * * * PARAMETERS: M * R: A real number to convert to a string. M * * * RETURN VALUE: M * char *: A string representing R allocated statically. M * * * SEE ALSO: M * IPSetPrintFunc, IPSetFloatFormat, IPPrintFunc M * * * KEYWORDS: M * IPCnvReal2Str, files M *****************************************************************************/ char *IPCnvReal2Str(RealType R) { return _IPReal2Str(R); } /***************************************************************************** * DESCRIPTION: M * Sets the printing function to call if needs to redirect printing. M * * * PARAMETERS: M * PrintFunc: A function that gets a single string it should print. M * * * RETURN VALUE: M * IPPrintFuncType: Old value of this state. M * * * SEE ALSO: M * IPCnvReal2Str, IPSetFloatFormat, IPPrintFunc M * * * KEYWORDS: M * IPSetPrintFunc, files M *****************************************************************************/ IPPrintFuncType IPSetPrintFunc(IPPrintFuncType PrintFunc) { IPPrintFuncType OldVal = IPPrintFunc; IPPrintFunc = PrintFunc; return OldVal; } /***************************************************************************** * DESCRIPTION: M * Sets the filtering mode of degenerated geomerty while save/load. M * * * PARAMETERS: M * FilterDegeneracies: TRUE to filter, FALSE to load/dump anyway. M * * * RETURN VALUE: M * int: Old value of this state. M * * * KEYWORDS: M * IPSetFilterDegen, files, degeneracies M *****************************************************************************/ int IPSetFilterDegen(int FilterDegeneracies) { int OldVal = _IPFilterDegeneracies; _IPFilterDegeneracies = FilterDegeneracies; return OldVal; } /***************************************************************************** * DESCRIPTION: M * Sets the floating point printing format. M * * * PARAMETERS: M * FloatFormat: A printf style floating point printing format string. M * * * RETURN VALUE: M * char *: old float format. M * * * KEYWORDS: M * IPSetFloatFormat, files M *****************************************************************************/ char *IPSetFloatFormat(char *FloatFormat) { STATIC_DATA char Str[LINE_LEN]; /* Not a full-proof test but something. */ if (strlen(FloatFormat) >= 2 && strchr(FloatFormat, '%') != NULL && (strchr(FloatFormat, 'e') != NULL || strchr(FloatFormat, 'f') != NULL || strchr(FloatFormat, 'g') != NULL || strchr(FloatFormat, 'E') != NULL || strchr(FloatFormat, 'F') != NULL || strchr(FloatFormat, 'G') != NULL)) { strcpy(Str, _IPGlblFloatFormat); _IPGlblFloatFormat = IritStrdup(FloatFormat); } else { sprintf(Str, IRIT_EXP_STR("Illegal floating point format \"%s\"."), FloatFormat); IPFatalError(Str); strcpy(Str, _IPGlblFloatFormat); } return Str; }