xref: /dflybsd-src/contrib/mpc/src/inp_str.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*d30dc8cbSJohn Marino /* mpc_inp_str -- Input a complex number from a given stream.
2*d30dc8cbSJohn Marino 
3*d30dc8cbSJohn Marino Copyright (C) 2009, 2010, 2011 INRIA
4*d30dc8cbSJohn Marino 
5*d30dc8cbSJohn Marino This file is part of GNU MPC.
6*d30dc8cbSJohn Marino 
7*d30dc8cbSJohn Marino GNU MPC is free software; you can redistribute it and/or modify it under
8*d30dc8cbSJohn Marino the terms of the GNU Lesser General Public License as published by the
9*d30dc8cbSJohn Marino Free Software Foundation; either version 3 of the License, or (at your
10*d30dc8cbSJohn Marino option) any later version.
11*d30dc8cbSJohn Marino 
12*d30dc8cbSJohn Marino GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13*d30dc8cbSJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14*d30dc8cbSJohn Marino FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15*d30dc8cbSJohn Marino more details.
16*d30dc8cbSJohn Marino 
17*d30dc8cbSJohn Marino You should have received a copy of the GNU Lesser General Public License
18*d30dc8cbSJohn Marino along with this program. If not, see http://www.gnu.org/licenses/ .
19*d30dc8cbSJohn Marino */
20*d30dc8cbSJohn Marino 
21*d30dc8cbSJohn Marino #include <stdio.h> /* for FILE */
22*d30dc8cbSJohn Marino #include <ctype.h>
23*d30dc8cbSJohn Marino #include <string.h>
24*d30dc8cbSJohn Marino #include "mpc-impl.h"
25*d30dc8cbSJohn Marino 
26*d30dc8cbSJohn Marino static size_t
skip_whitespace(FILE * stream)27*d30dc8cbSJohn Marino skip_whitespace (FILE *stream)
28*d30dc8cbSJohn Marino {
29*d30dc8cbSJohn Marino    int c = getc (stream);
30*d30dc8cbSJohn Marino    size_t size = 0;
31*d30dc8cbSJohn Marino    while (c != EOF && isspace ((unsigned char) c)) {
32*d30dc8cbSJohn Marino       c = getc (stream);
33*d30dc8cbSJohn Marino       size++;
34*d30dc8cbSJohn Marino    }
35*d30dc8cbSJohn Marino    if (c != EOF)
36*d30dc8cbSJohn Marino       ungetc (c, stream);
37*d30dc8cbSJohn Marino    return size;
38*d30dc8cbSJohn Marino }
39*d30dc8cbSJohn Marino 
40*d30dc8cbSJohn Marino /* Extract from stream the longest string made up of alphanumeric char and
41*d30dc8cbSJohn Marino    '_' (i.e. n-char-sequence).
42*d30dc8cbSJohn Marino    The user must free the returned string. */
43*d30dc8cbSJohn Marino static char *
extract_suffix(FILE * stream)44*d30dc8cbSJohn Marino extract_suffix (FILE *stream)
45*d30dc8cbSJohn Marino {
46*d30dc8cbSJohn Marino   int c;
47*d30dc8cbSJohn Marino   size_t nread = 0;
48*d30dc8cbSJohn Marino   size_t strsize = 100;
49*d30dc8cbSJohn Marino   char *str = mpc_alloc_str (strsize);
50*d30dc8cbSJohn Marino 
51*d30dc8cbSJohn Marino   c = getc (stream);
52*d30dc8cbSJohn Marino   while (isalnum ((unsigned char) c) || c == '_') {
53*d30dc8cbSJohn Marino     str [nread] = (char) c;
54*d30dc8cbSJohn Marino     nread++;
55*d30dc8cbSJohn Marino     if (nread == strsize) {
56*d30dc8cbSJohn Marino       str = mpc_realloc_str (str, strsize, 2 * strsize);
57*d30dc8cbSJohn Marino       strsize *= 2;
58*d30dc8cbSJohn Marino          }
59*d30dc8cbSJohn Marino     c = getc (stream);
60*d30dc8cbSJohn Marino   }
61*d30dc8cbSJohn Marino 
62*d30dc8cbSJohn Marino   str = mpc_realloc_str (str, strsize, nread + 1);
63*d30dc8cbSJohn Marino   strsize = nread + 1;
64*d30dc8cbSJohn Marino   str [nread] = '\0';
65*d30dc8cbSJohn Marino 
66*d30dc8cbSJohn Marino   if (c != EOF)
67*d30dc8cbSJohn Marino     ungetc (c, stream);
68*d30dc8cbSJohn Marino   return str;
69*d30dc8cbSJohn Marino }
70*d30dc8cbSJohn Marino 
71*d30dc8cbSJohn Marino 
72*d30dc8cbSJohn Marino /* Extract from the stream the longest string of characters which are neither
73*d30dc8cbSJohn Marino    whitespace nor brackets (except for an optional bracketed n-char_sequence
74*d30dc8cbSJohn Marino    directly following nan or @nan@ independently of case).
75*d30dc8cbSJohn Marino    The user must free the returned string.                                    */
76*d30dc8cbSJohn Marino static char *
extract_string(FILE * stream)77*d30dc8cbSJohn Marino extract_string (FILE *stream)
78*d30dc8cbSJohn Marino {
79*d30dc8cbSJohn Marino   int c;
80*d30dc8cbSJohn Marino   size_t nread = 0;
81*d30dc8cbSJohn Marino   size_t strsize = 100;
82*d30dc8cbSJohn Marino   char *str = mpc_alloc_str (strsize);
83*d30dc8cbSJohn Marino   size_t lenstr;
84*d30dc8cbSJohn Marino 
85*d30dc8cbSJohn Marino   c = getc (stream);
86*d30dc8cbSJohn Marino   while (c != EOF && c != '\n'
87*d30dc8cbSJohn Marino          && !isspace ((unsigned char) c)
88*d30dc8cbSJohn Marino          && c != '(' && c != ')') {
89*d30dc8cbSJohn Marino     str [nread] = (char) c;
90*d30dc8cbSJohn Marino     nread++;
91*d30dc8cbSJohn Marino     if (nread == strsize) {
92*d30dc8cbSJohn Marino       str = mpc_realloc_str (str, strsize, 2 * strsize);
93*d30dc8cbSJohn Marino       strsize *= 2;
94*d30dc8cbSJohn Marino     }
95*d30dc8cbSJohn Marino     c = getc (stream);
96*d30dc8cbSJohn Marino   }
97*d30dc8cbSJohn Marino 
98*d30dc8cbSJohn Marino   str = mpc_realloc_str (str, strsize, nread + 1);
99*d30dc8cbSJohn Marino   strsize = nread + 1;
100*d30dc8cbSJohn Marino   str [nread] = '\0';
101*d30dc8cbSJohn Marino 
102*d30dc8cbSJohn Marino   if (nread == 0)
103*d30dc8cbSJohn Marino     return str;
104*d30dc8cbSJohn Marino 
105*d30dc8cbSJohn Marino   lenstr = nread;
106*d30dc8cbSJohn Marino 
107*d30dc8cbSJohn Marino   if (c == '(') {
108*d30dc8cbSJohn Marino     size_t n;
109*d30dc8cbSJohn Marino     char *suffix;
110*d30dc8cbSJohn Marino     int ret;
111*d30dc8cbSJohn Marino 
112*d30dc8cbSJohn Marino     /* (n-char-sequence) only after a NaN */
113*d30dc8cbSJohn Marino     if ((nread != 3
114*d30dc8cbSJohn Marino          || tolower ((unsigned char) (str[0])) != 'n'
115*d30dc8cbSJohn Marino          || tolower ((unsigned char) (str[1])) != 'a'
116*d30dc8cbSJohn Marino          || tolower ((unsigned char) (str[2])) != 'n')
117*d30dc8cbSJohn Marino         && (nread != 5
118*d30dc8cbSJohn Marino             || str[0] != '@'
119*d30dc8cbSJohn Marino             || tolower ((unsigned char) (str[1])) != 'n'
120*d30dc8cbSJohn Marino             || tolower ((unsigned char) (str[2])) != 'a'
121*d30dc8cbSJohn Marino             || tolower ((unsigned char) (str[3])) != 'n'
122*d30dc8cbSJohn Marino             || str[4] != '@')) {
123*d30dc8cbSJohn Marino       ungetc (c, stream);
124*d30dc8cbSJohn Marino       return str;
125*d30dc8cbSJohn Marino     }
126*d30dc8cbSJohn Marino 
127*d30dc8cbSJohn Marino     suffix = extract_suffix (stream);
128*d30dc8cbSJohn Marino     nread += strlen (suffix) + 1;
129*d30dc8cbSJohn Marino     if (nread >= strsize) {
130*d30dc8cbSJohn Marino       str = mpc_realloc_str (str, strsize, nread + 1);
131*d30dc8cbSJohn Marino       strsize = nread + 1;
132*d30dc8cbSJohn Marino     }
133*d30dc8cbSJohn Marino 
134*d30dc8cbSJohn Marino     /* Warning: the sprintf does not allow overlap between arguments. */
135*d30dc8cbSJohn Marino     ret = sprintf (str + lenstr, "(%s", suffix);
136*d30dc8cbSJohn Marino     MPC_ASSERT (ret >= 0);
137*d30dc8cbSJohn Marino     n = lenstr + (size_t) ret;
138*d30dc8cbSJohn Marino     MPC_ASSERT (n == nread);
139*d30dc8cbSJohn Marino 
140*d30dc8cbSJohn Marino     c = getc (stream);
141*d30dc8cbSJohn Marino     if (c == ')') {
142*d30dc8cbSJohn Marino       str = mpc_realloc_str (str, strsize, nread + 2);
143*d30dc8cbSJohn Marino       strsize = nread + 2;
144*d30dc8cbSJohn Marino       str [nread] = (char) c;
145*d30dc8cbSJohn Marino       str [nread+1] = '\0';
146*d30dc8cbSJohn Marino       nread++;
147*d30dc8cbSJohn Marino     }
148*d30dc8cbSJohn Marino     else if (c != EOF)
149*d30dc8cbSJohn Marino       ungetc (c, stream);
150*d30dc8cbSJohn Marino 
151*d30dc8cbSJohn Marino     mpc_free_str (suffix);
152*d30dc8cbSJohn Marino   }
153*d30dc8cbSJohn Marino   else if (c != EOF)
154*d30dc8cbSJohn Marino     ungetc (c, stream);
155*d30dc8cbSJohn Marino 
156*d30dc8cbSJohn Marino   return str;
157*d30dc8cbSJohn Marino }
158*d30dc8cbSJohn Marino 
159*d30dc8cbSJohn Marino 
160*d30dc8cbSJohn Marino int
mpc_inp_str(mpc_ptr rop,FILE * stream,size_t * read,int base,mpc_rnd_t rnd_mode)161*d30dc8cbSJohn Marino mpc_inp_str (mpc_ptr rop, FILE *stream, size_t *read, int base,
162*d30dc8cbSJohn Marino mpc_rnd_t rnd_mode)
163*d30dc8cbSJohn Marino {
164*d30dc8cbSJohn Marino    size_t white, nread = 0;
165*d30dc8cbSJohn Marino    int inex = -1;
166*d30dc8cbSJohn Marino    int c;
167*d30dc8cbSJohn Marino    char *str;
168*d30dc8cbSJohn Marino 
169*d30dc8cbSJohn Marino    if (stream == NULL)
170*d30dc8cbSJohn Marino       stream = stdin;
171*d30dc8cbSJohn Marino 
172*d30dc8cbSJohn Marino    white = skip_whitespace (stream);
173*d30dc8cbSJohn Marino    c = getc (stream);
174*d30dc8cbSJohn Marino    if (c != EOF) {
175*d30dc8cbSJohn Marino      if (c == '(') {
176*d30dc8cbSJohn Marino        char *real_str;
177*d30dc8cbSJohn Marino        char *imag_str;
178*d30dc8cbSJohn Marino        size_t n;
179*d30dc8cbSJohn Marino        int ret;
180*d30dc8cbSJohn Marino 
181*d30dc8cbSJohn Marino        nread++; /* the opening parenthesis */
182*d30dc8cbSJohn Marino        white = skip_whitespace (stream);
183*d30dc8cbSJohn Marino        real_str = extract_string (stream);
184*d30dc8cbSJohn Marino        nread += strlen(real_str);
185*d30dc8cbSJohn Marino 
186*d30dc8cbSJohn Marino        c = getc (stream);
187*d30dc8cbSJohn Marino        if (!isspace ((unsigned int) c)) {
188*d30dc8cbSJohn Marino          if (c != EOF)
189*d30dc8cbSJohn Marino            ungetc (c, stream);
190*d30dc8cbSJohn Marino          mpc_free_str (real_str);
191*d30dc8cbSJohn Marino          goto error;
192*d30dc8cbSJohn Marino        }
193*d30dc8cbSJohn Marino        else
194*d30dc8cbSJohn Marino          ungetc (c, stream);
195*d30dc8cbSJohn Marino 
196*d30dc8cbSJohn Marino        white += skip_whitespace (stream);
197*d30dc8cbSJohn Marino        imag_str = extract_string (stream);
198*d30dc8cbSJohn Marino        nread += strlen (imag_str);
199*d30dc8cbSJohn Marino 
200*d30dc8cbSJohn Marino        str = mpc_alloc_str (nread + 2);
201*d30dc8cbSJohn Marino        ret = sprintf (str, "(%s %s", real_str, imag_str);
202*d30dc8cbSJohn Marino        MPC_ASSERT (ret >= 0);
203*d30dc8cbSJohn Marino        n = (size_t) ret;
204*d30dc8cbSJohn Marino        MPC_ASSERT (n == nread + 1);
205*d30dc8cbSJohn Marino        mpc_free_str (real_str);
206*d30dc8cbSJohn Marino        mpc_free_str (imag_str);
207*d30dc8cbSJohn Marino 
208*d30dc8cbSJohn Marino        white += skip_whitespace (stream);
209*d30dc8cbSJohn Marino        c = getc (stream);
210*d30dc8cbSJohn Marino        if (c == ')') {
211*d30dc8cbSJohn Marino          str = mpc_realloc_str (str, nread +2, nread + 3);
212*d30dc8cbSJohn Marino          str [nread+1] = (char) c;
213*d30dc8cbSJohn Marino          str [nread+2] = '\0';
214*d30dc8cbSJohn Marino          nread++;
215*d30dc8cbSJohn Marino        }
216*d30dc8cbSJohn Marino        else if (c != EOF)
217*d30dc8cbSJohn Marino          ungetc (c, stream);
218*d30dc8cbSJohn Marino      }
219*d30dc8cbSJohn Marino      else {
220*d30dc8cbSJohn Marino        if (c != EOF)
221*d30dc8cbSJohn Marino          ungetc (c, stream);
222*d30dc8cbSJohn Marino        str = extract_string (stream);
223*d30dc8cbSJohn Marino        nread += strlen (str);
224*d30dc8cbSJohn Marino      }
225*d30dc8cbSJohn Marino 
226*d30dc8cbSJohn Marino      inex = mpc_set_str (rop, str, base, rnd_mode);
227*d30dc8cbSJohn Marino 
228*d30dc8cbSJohn Marino      mpc_free_str (str);
229*d30dc8cbSJohn Marino    }
230*d30dc8cbSJohn Marino 
231*d30dc8cbSJohn Marino error:
232*d30dc8cbSJohn Marino    if (inex == -1) {
233*d30dc8cbSJohn Marino       mpfr_set_nan (mpc_realref(rop));
234*d30dc8cbSJohn Marino       mpfr_set_nan (mpc_imagref(rop));
235*d30dc8cbSJohn Marino    }
236*d30dc8cbSJohn Marino    if (read != NULL)
237*d30dc8cbSJohn Marino      *read = white + nread;
238*d30dc8cbSJohn Marino    return inex;
239*d30dc8cbSJohn Marino }
240