/****************************************************************************** * Bzr-Read.c - Bezier curves handling routines - read from file. * ******************************************************************************* * Written by Gershon Elber, Mar. 90. * ******************************************************************************/ #ifdef __MSDOS__ #include #endif /* __MSDOS__ */ #include #include #include #include "cagd_loc.h" #define UNGET_STACK_SIZE 3 int _CagdGlblLineCount = 1; /* Used to locate errors in input file. */ static int GlblTknStackSize = 0; /* Used by parser, to unget token. */ static char GlblStringToken[UNGET_STACK_SIZE][LINE_LEN];/* Save unget tokens.*/ static void GetStringToken(FILE *f, char *StringToken); /***************************************************************************** * Routine to read from input file f the following [ATTR ...] [ATTR ...]. * * Note the '[' was allready read. * * Current supported attributes: None. * * Returns NULL if O.k., otherwise string describing the error. * *****************************************************************************/ char *_CagdGetCurveAttributes(FILE *f) { TokenNumType i; char StringToken[LINE_LEN]; do { switch (_CagdGetToken(f, StringToken)) { default: while ((i = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN && i != TOKEN_EOF); if (i == TOKEN_EOF) return "EOF detected in middle of attribute."; break; } } while (_CagdGetToken(f, StringToken) == TOKEN_OPEN_PAREN); _CagdUnGetToken(StringToken); return NULL; } /***************************************************************************** * Routine to read from input file f the following [ATTR ...] [ATTR ...]. * * Note the '[' was allready read. * * Current supported attributes: None. * * Returns NULL if O.k., otherwise string describing the error. * *****************************************************************************/ char *_CagdGetSurfaceAttributes(FILE *f) { TokenNumType i; char StringToken[LINE_LEN]; do { switch (_CagdGetToken(f, StringToken)) { default: while ((i = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN && i != TOKEN_EOF); if (i == TOKEN_EOF) return "EOF detected in middle of attribute."; break; } } while (_CagdGetToken(f, StringToken) == TOKEN_OPEN_PAREN); _CagdUnGetToken(StringToken); return NULL; } /****************************************************************************** * Routine to unget one token (on stack of UNGET_STACK_SIZE levels!) * ******************************************************************************/ void _CagdUnGetToken(char *StringToken) { if (GlblTknStackSize >= UNGET_STACK_SIZE) FATAL_ERROR(CAGD_ERR_PARSER_STACK_OV); strcpy(GlblStringToken[GlblTknStackSize++], StringToken); } /****************************************************************************** * 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 (GlblTknStackSize) { /* Get first the unget token. */ strcpy(StringToken, GlblStringToken[--GlblTknStackSize]); return; } /* skip white spaces and comments: */ while (!feof(f) && ((c = getc(f)) == ' ' || c == '\t' || c == '\n') || c == '#') { /* Skip a comment if encounter one. */ if (c == '#') while (!feof(f) && c != '\n') c = getc(f); if (c == '\n') _CagdGlblLineCount++; /* 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 = 0; /* 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 CloseParen */ _CagdUnGetToken(&StringToken[Len]); /* Save next token. */ StringToken[Len] = 0; /* 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! * ******************************************************************************/ TokenNumType _CagdGetToken(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, "BEZIER")) return TOKEN_BEZIER; if (!strcmp(StringToken, "BSPLINE")) return TOKEN_BSPLINE; if (!strcmp(StringToken, "POWER")) return TOKEN_POWER; if (!strcmp(StringToken, "CURVE")) return TOKEN_CURVE; if (!strcmp(StringToken, "SURFACE")) return TOKEN_SURFACE; if (!strcmp(StringToken, "PTYPE")) return TOKEN_PTYPE; if (!strcmp(StringToken, "NUMPTS")) return TOKEN_NUM_PTS; if (!strcmp(StringToken, "ORDER")) return TOKEN_ORDER; if (!strcmp(StringToken, "KV")) return TOKEN_KV; return TOKEN_OTHER; /* Must be number or name. */ } /***************************************************************************** * Convert a real number into a string. * *****************************************************************************/ char *_CagdReal2Str(double R) { static char Buffer[LINE_LEN]; int j; if (ABS(R) < EPSILON) R = 0.0; sprintf(Buffer, "%-8.6lg", R); for (j = strlen(Buffer) - 1; Buffer[j] == ' ' && j > 0; j--); if (strchr(Buffer, '.') != NULL) for (; Buffer[j] == '0' && j > 0; j--); Buffer[j+1] = 0; return Buffer; }