/* mpc_inp_str -- Input a complex number from a given stream. Copyright (C) 2009, 2010, 2011 INRIA This file is part of GNU MPC. GNU MPC is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses/ . */ #include /* for FILE */ #include #include #include "mpc-impl.h" static size_t skip_whitespace (FILE *stream) { int c = getc (stream); size_t size = 0; while (c != EOF && isspace ((unsigned char) c)) { c = getc (stream); size++; } if (c != EOF) ungetc (c, stream); return size; } /* Extract from stream the longest string made up of alphanumeric char and '_' (i.e. n-char-sequence). The user must free the returned string. */ static char * extract_suffix (FILE *stream) { int c; size_t nread = 0; size_t strsize = 100; char *str = mpc_alloc_str (strsize); c = getc (stream); while (isalnum ((unsigned char) c) || c == '_') { str [nread] = (char) c; nread++; if (nread == strsize) { str = mpc_realloc_str (str, strsize, 2 * strsize); strsize *= 2; } c = getc (stream); } str = mpc_realloc_str (str, strsize, nread + 1); strsize = nread + 1; str [nread] = '\0'; if (c != EOF) ungetc (c, stream); return str; } /* Extract from the stream the longest string of characters which are neither whitespace nor brackets (except for an optional bracketed n-char_sequence directly following nan or @nan@ independently of case). The user must free the returned string. */ static char * extract_string (FILE *stream) { int c; size_t nread = 0; size_t strsize = 100; char *str = mpc_alloc_str (strsize); size_t lenstr; c = getc (stream); while (c != EOF && c != '\n' && !isspace ((unsigned char) c) && c != '(' && c != ')') { str [nread] = (char) c; nread++; if (nread == strsize) { str = mpc_realloc_str (str, strsize, 2 * strsize); strsize *= 2; } c = getc (stream); } str = mpc_realloc_str (str, strsize, nread + 1); strsize = nread + 1; str [nread] = '\0'; if (nread == 0) return str; lenstr = nread; if (c == '(') { size_t n; char *suffix; int ret; /* (n-char-sequence) only after a NaN */ if ((nread != 3 || tolower ((unsigned char) (str[0])) != 'n' || tolower ((unsigned char) (str[1])) != 'a' || tolower ((unsigned char) (str[2])) != 'n') && (nread != 5 || str[0] != '@' || tolower ((unsigned char) (str[1])) != 'n' || tolower ((unsigned char) (str[2])) != 'a' || tolower ((unsigned char) (str[3])) != 'n' || str[4] != '@')) { ungetc (c, stream); return str; } suffix = extract_suffix (stream); nread += strlen (suffix) + 1; if (nread >= strsize) { str = mpc_realloc_str (str, strsize, nread + 1); strsize = nread + 1; } /* Warning: the sprintf does not allow overlap between arguments. */ ret = sprintf (str + lenstr, "(%s", suffix); MPC_ASSERT (ret >= 0); n = lenstr + (size_t) ret; MPC_ASSERT (n == nread); c = getc (stream); if (c == ')') { str = mpc_realloc_str (str, strsize, nread + 2); strsize = nread + 2; str [nread] = (char) c; str [nread+1] = '\0'; nread++; } else if (c != EOF) ungetc (c, stream); mpc_free_str (suffix); } else if (c != EOF) ungetc (c, stream); return str; } int mpc_inp_str (mpc_ptr rop, FILE *stream, size_t *read, int base, mpc_rnd_t rnd_mode) { size_t white, nread = 0; int inex = -1; int c; char *str; if (stream == NULL) stream = stdin; white = skip_whitespace (stream); c = getc (stream); if (c != EOF) { if (c == '(') { char *real_str; char *imag_str; size_t n; int ret; nread++; /* the opening parenthesis */ white = skip_whitespace (stream); real_str = extract_string (stream); nread += strlen(real_str); c = getc (stream); if (!isspace ((unsigned int) c)) { if (c != EOF) ungetc (c, stream); mpc_free_str (real_str); goto error; } else ungetc (c, stream); white += skip_whitespace (stream); imag_str = extract_string (stream); nread += strlen (imag_str); str = mpc_alloc_str (nread + 2); ret = sprintf (str, "(%s %s", real_str, imag_str); MPC_ASSERT (ret >= 0); n = (size_t) ret; MPC_ASSERT (n == nread + 1); mpc_free_str (real_str); mpc_free_str (imag_str); white += skip_whitespace (stream); c = getc (stream); if (c == ')') { str = mpc_realloc_str (str, nread +2, nread + 3); str [nread+1] = (char) c; str [nread+2] = '\0'; nread++; } else if (c != EOF) ungetc (c, stream); } else { if (c != EOF) ungetc (c, stream); str = extract_string (stream); nread += strlen (str); } inex = mpc_set_str (rop, str, base, rnd_mode); mpc_free_str (str); } error: if (inex == -1) { mpfr_set_nan (mpc_realref(rop)); mpfr_set_nan (mpc_imagref(rop)); } if (read != NULL) *read = white + nread; return inex; }