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