Blame src/inp_str.c

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
}