1*5273c5e4Smrg /* read_description.c -- read parameters from description file
2*5273c5e4Smrg
3*5273c5e4Smrg Copyright (C) 2012, 2013, 2014 INRIA
4*5273c5e4Smrg
5*5273c5e4Smrg This file is part of GNU MPC.
6*5273c5e4Smrg
7*5273c5e4Smrg GNU MPC is free software; you can redistribute it and/or modify it under
8*5273c5e4Smrg the terms of the GNU Lesser General Public License as published by the
9*5273c5e4Smrg Free Software Foundation; either version 3 of the License, or (at your
10*5273c5e4Smrg option) any later version.
11*5273c5e4Smrg
12*5273c5e4Smrg GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13*5273c5e4Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14*5273c5e4Smrg FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15*5273c5e4Smrg more details.
16*5273c5e4Smrg
17*5273c5e4Smrg You should have received a copy of the GNU Lesser General Public License
18*5273c5e4Smrg along with this program. If not, see http://www.gnu.org/licenses/ .
19*5273c5e4Smrg */
20*5273c5e4Smrg
21*5273c5e4Smrg #include <string.h>
22*5273c5e4Smrg #include "mpc-tests.h"
23*5273c5e4Smrg
24*5273c5e4Smrg static size_t read_keyworddesc (mpc_datafile_context_t* datafile_context,
25*5273c5e4Smrg char **buffer_ptr, size_t buffer_length);
26*5273c5e4Smrg
27*5273c5e4Smrg /* tuple to link name with the enum value */
28*5273c5e4Smrg typedef struct {
29*5273c5e4Smrg const char * name; /* type name */
30*5273c5e4Smrg mpc_param_t val; /* type enum */
31*5273c5e4Smrg } param_typeval_t;
32*5273c5e4Smrg
33*5273c5e4Smrg /* available types for function description */
34*5273c5e4Smrg static const param_typeval_t sparam_typeval[]= {
35*5273c5e4Smrg { "int" , NATIVE_INT },
36*5273c5e4Smrg { "unsigned long int" , NATIVE_UL },
37*5273c5e4Smrg { "unsigned long" , NATIVE_UL },
38*5273c5e4Smrg { "long int" , NATIVE_L },
39*5273c5e4Smrg { "long" , NATIVE_L },
40*5273c5e4Smrg { "double" , NATIVE_D },
41*5273c5e4Smrg { "long double" , NATIVE_LD },
42*5273c5e4Smrg { "double _Complex" , NATIVE_DC },
43*5273c5e4Smrg { "long double _Complex", NATIVE_LDC },
44*5273c5e4Smrg { "intmax_t" , NATIVE_IM },
45*5273c5e4Smrg { "uintmax_t" , NATIVE_UIM },
46*5273c5e4Smrg { "mpz_ptr" , GMP_Z },
47*5273c5e4Smrg { "mpz_srcptr" , GMP_Z },
48*5273c5e4Smrg { "mpq_ptr" , GMP_Q },
49*5273c5e4Smrg { "mpq_srcptr" , GMP_Q },
50*5273c5e4Smrg { "mpf_ptr" , GMP_F },
51*5273c5e4Smrg { "mpf_srcptr" , GMP_F },
52*5273c5e4Smrg { "mpfr_inex" , MPFR_INEX },
53*5273c5e4Smrg { "mpfr_ptr" , MPFR },
54*5273c5e4Smrg { "mpfr_srcptr" , MPFR },
55*5273c5e4Smrg { "mpfr_rnd_t" , MPFR_RND },
56*5273c5e4Smrg { "mpc_inex" , MPC_INEX },
57*5273c5e4Smrg { "mpc_ptr" , MPC },
58*5273c5e4Smrg { "mpc_srcptr" , MPC },
59*5273c5e4Smrg { "mpc_rnd_t" , MPC_RND },
60*5273c5e4Smrg { "mpcc_inex" , MPCC_INEX }
61*5273c5e4Smrg };
62*5273c5e4Smrg
63*5273c5e4Smrg /* read primitives */
64*5273c5e4Smrg
65*5273c5e4Smrg static size_t
read_keyworddesc(mpc_datafile_context_t * datafile_context,char ** buffer_ptr,size_t buffer_length)66*5273c5e4Smrg read_keyworddesc (mpc_datafile_context_t* datafile_context,
67*5273c5e4Smrg char **buffer_ptr,
68*5273c5e4Smrg size_t buffer_length)
69*5273c5e4Smrg {
70*5273c5e4Smrg size_t pos;
71*5273c5e4Smrg char *buffer;
72*5273c5e4Smrg
73*5273c5e4Smrg pos = 0;
74*5273c5e4Smrg buffer = *buffer_ptr;
75*5273c5e4Smrg
76*5273c5e4Smrg while (datafile_context->nextchar != EOF
77*5273c5e4Smrg && datafile_context->nextchar != '#'
78*5273c5e4Smrg && datafile_context->nextchar != '\n')
79*5273c5e4Smrg {
80*5273c5e4Smrg if (pos + 1 > buffer_length)
81*5273c5e4Smrg {
82*5273c5e4Smrg if (buffer_length == 0)
83*5273c5e4Smrg buffer_length = pos + 1;
84*5273c5e4Smrg buffer = (char *) realloc (buffer, 2 * buffer_length);
85*5273c5e4Smrg buffer_length *= 2;
86*5273c5e4Smrg if (buffer == NULL)
87*5273c5e4Smrg {
88*5273c5e4Smrg printf ("Cannot allocate memory\n");
89*5273c5e4Smrg exit (1);
90*5273c5e4Smrg }
91*5273c5e4Smrg }
92*5273c5e4Smrg buffer[pos++] = (char) datafile_context->nextchar;
93*5273c5e4Smrg datafile_context->nextchar = getc (datafile_context->fd);
94*5273c5e4Smrg }
95*5273c5e4Smrg while (pos>0 && isspace(buffer[pos-1])) pos--;
96*5273c5e4Smrg
97*5273c5e4Smrg if (pos + 1 > buffer_length)
98*5273c5e4Smrg {
99*5273c5e4Smrg buffer = (char *) realloc (buffer, buffer_length + 1);
100*5273c5e4Smrg buffer_length++;
101*5273c5e4Smrg if (buffer == NULL)
102*5273c5e4Smrg {
103*5273c5e4Smrg printf ("Cannot allocate memory\n");
104*5273c5e4Smrg exit (1);
105*5273c5e4Smrg }
106*5273c5e4Smrg }
107*5273c5e4Smrg buffer[pos] = '\0';
108*5273c5e4Smrg
109*5273c5e4Smrg *buffer_ptr = buffer;
110*5273c5e4Smrg
111*5273c5e4Smrg return buffer_length;
112*5273c5e4Smrg }
113*5273c5e4Smrg
114*5273c5e4Smrg /* return the enum associated to name */
115*5273c5e4Smrg static mpc_param_t
description_findtype(const char * name)116*5273c5e4Smrg description_findtype (const char *name)
117*5273c5e4Smrg {
118*5273c5e4Smrg
119*5273c5e4Smrg mpc_param_t r = sparam_typeval[0].val;
120*5273c5e4Smrg size_t s = 0;
121*5273c5e4Smrg const size_t send = sizeof (sparam_typeval) / sizeof (param_typeval_t);
122*5273c5e4Smrg
123*5273c5e4Smrg while (s < send && strcmp (sparam_typeval[s].name, name) != 0)
124*5273c5e4Smrg s++;
125*5273c5e4Smrg
126*5273c5e4Smrg if (s < send)
127*5273c5e4Smrg r = sparam_typeval[s].val;
128*5273c5e4Smrg else
129*5273c5e4Smrg {
130*5273c5e4Smrg printf ("Error: Unable to find the type '%s'\n",name);
131*5273c5e4Smrg exit (1);
132*5273c5e4Smrg }
133*5273c5e4Smrg return r;
134*5273c5e4Smrg }
135*5273c5e4Smrg
136*5273c5e4Smrg /* return the name associated to the enum */
137*5273c5e4Smrg const char*
read_description_findname(mpc_param_t e)138*5273c5e4Smrg read_description_findname (mpc_param_t e)
139*5273c5e4Smrg {
140*5273c5e4Smrg
141*5273c5e4Smrg const char * name = NULL;
142*5273c5e4Smrg size_t s = 0;
143*5273c5e4Smrg const size_t send = sizeof (sparam_typeval) / sizeof (param_typeval_t);
144*5273c5e4Smrg
145*5273c5e4Smrg while (s < send && sparam_typeval[s].val != e)
146*5273c5e4Smrg s++;
147*5273c5e4Smrg
148*5273c5e4Smrg if (s<send)
149*5273c5e4Smrg name = sparam_typeval[s].name;
150*5273c5e4Smrg else
151*5273c5e4Smrg {
152*5273c5e4Smrg printf ("Error: Unable to find the enum type\n");
153*5273c5e4Smrg exit (1);
154*5273c5e4Smrg }
155*5273c5e4Smrg return name;
156*5273c5e4Smrg }
157*5273c5e4Smrg
158*5273c5e4Smrg
159*5273c5e4Smrg /* read the description file and fill param */
160*5273c5e4Smrg void
read_description(mpc_fun_param_t * param,const char * filename)161*5273c5e4Smrg read_description (mpc_fun_param_t* param, const char *filename)
162*5273c5e4Smrg {
163*5273c5e4Smrg mpc_datafile_context_t datafile_context;
164*5273c5e4Smrg const char *pathname = filename;
165*5273c5e4Smrg char *namestr = NULL;
166*5273c5e4Smrg char *buffer = NULL;
167*5273c5e4Smrg size_t len = 0;
168*5273c5e4Smrg int nbout = 0;
169*5273c5e4Smrg int nbin = 0;
170*5273c5e4Smrg int rnd_mode = 0;
171*5273c5e4Smrg int j;
172*5273c5e4Smrg
173*5273c5e4Smrg open_datafile (&datafile_context, filename);
174*5273c5e4Smrg
175*5273c5e4Smrg /* read NAME fields */
176*5273c5e4Smrg tpl_skip_whitespace_comments(&datafile_context);
177*5273c5e4Smrg len = read_keyworddesc (&datafile_context, &namestr, len);
178*5273c5e4Smrg if (namestr == NULL || strcmp (namestr,"NAME:") != 0)
179*5273c5e4Smrg {
180*5273c5e4Smrg printf ("Error: Unable to read 'NAME:' in file '%s'\n",
181*5273c5e4Smrg filename);
182*5273c5e4Smrg exit (1);
183*5273c5e4Smrg }
184*5273c5e4Smrg
185*5273c5e4Smrg tpl_skip_whitespace_comments (&datafile_context);
186*5273c5e4Smrg read_keyworddesc (&datafile_context, &namestr, len);
187*5273c5e4Smrg if (namestr == NULL)
188*5273c5e4Smrg {
189*5273c5e4Smrg printf ("Error: Unable to read the name of the function in file '%s'\n",
190*5273c5e4Smrg filename);
191*5273c5e4Smrg exit (1);
192*5273c5e4Smrg }
193*5273c5e4Smrg param->name = namestr;
194*5273c5e4Smrg namestr = NULL;
195*5273c5e4Smrg
196*5273c5e4Smrg /* read RETURN fields */
197*5273c5e4Smrg tpl_skip_whitespace_comments (&datafile_context);
198*5273c5e4Smrg len = 0;
199*5273c5e4Smrg len = read_keyworddesc (&datafile_context, &buffer, len);
200*5273c5e4Smrg if (buffer == NULL || strcmp (buffer,"RETURN:") != 0)
201*5273c5e4Smrg {
202*5273c5e4Smrg printf ("Error: Unable to read 'RETURN:' in file '%s'\n",
203*5273c5e4Smrg pathname);
204*5273c5e4Smrg exit (1);
205*5273c5e4Smrg }
206*5273c5e4Smrg
207*5273c5e4Smrg tpl_skip_whitespace_comments (&datafile_context);
208*5273c5e4Smrg len = read_keyworddesc (&datafile_context, &buffer, len);
209*5273c5e4Smrg if (buffer == NULL)
210*5273c5e4Smrg {
211*5273c5e4Smrg printf ("Error: Unable to read the return type of the function"
212*5273c5e4Smrg " in file '%s'\n", pathname);
213*5273c5e4Smrg exit (1);
214*5273c5e4Smrg }
215*5273c5e4Smrg param->T[nbout++] = description_findtype (buffer);
216*5273c5e4Smrg
217*5273c5e4Smrg /* read OUPUT fields */
218*5273c5e4Smrg tpl_skip_whitespace_comments (&datafile_context);
219*5273c5e4Smrg len = read_keyworddesc (&datafile_context, &buffer, len);
220*5273c5e4Smrg if (buffer == NULL || strcmp (buffer,"OUTPUT:")!=0)
221*5273c5e4Smrg {
222*5273c5e4Smrg printf ("Error: Unable to read 'OUTPUT:' in file '%s'\n",
223*5273c5e4Smrg pathname);
224*5273c5e4Smrg exit (1);
225*5273c5e4Smrg }
226*5273c5e4Smrg
227*5273c5e4Smrg while (!feof (datafile_context.fd))
228*5273c5e4Smrg {
229*5273c5e4Smrg tpl_skip_whitespace_comments (&datafile_context);
230*5273c5e4Smrg len = read_keyworddesc (&datafile_context, &buffer, len);
231*5273c5e4Smrg if (buffer == NULL)
232*5273c5e4Smrg {
233*5273c5e4Smrg printf ("Error: Unable to read the output type of the function"
234*5273c5e4Smrg " in file '%s'\n", pathname);
235*5273c5e4Smrg exit (1);
236*5273c5e4Smrg }
237*5273c5e4Smrg if (strcmp (buffer, "INPUT:") == 0)
238*5273c5e4Smrg break; /* exit the output loop */
239*5273c5e4Smrg param->T[nbout++] = description_findtype (buffer);
240*5273c5e4Smrg }
241*5273c5e4Smrg
242*5273c5e4Smrg /* read INPUT fields */
243*5273c5e4Smrg while (!feof (datafile_context.fd))
244*5273c5e4Smrg {
245*5273c5e4Smrg tpl_skip_whitespace_comments (&datafile_context);
246*5273c5e4Smrg len = read_keyworddesc (&datafile_context, &buffer, len);
247*5273c5e4Smrg if (buffer == NULL)
248*5273c5e4Smrg {
249*5273c5e4Smrg printf ("Error: Unable to read the input type of the function"
250*5273c5e4Smrg " in file '%s'\n", pathname);
251*5273c5e4Smrg exit (1);
252*5273c5e4Smrg }
253*5273c5e4Smrg if (strlen (buffer) == 0 && feof (datafile_context.fd))
254*5273c5e4Smrg break;
255*5273c5e4Smrg param->T[nbout+nbin] = description_findtype (buffer);
256*5273c5e4Smrg if (param->T[nbout+nbin] == MPC_RND || param->T[nbout+nbin] == MPFR_RND)
257*5273c5e4Smrg rnd_mode++;
258*5273c5e4Smrg nbin++;
259*5273c5e4Smrg }
260*5273c5e4Smrg free (buffer);
261*5273c5e4Smrg
262*5273c5e4Smrg param->nbout = nbout;
263*5273c5e4Smrg param->nbin = nbin;
264*5273c5e4Smrg param->nbrnd = rnd_mode;
265*5273c5e4Smrg
266*5273c5e4Smrg /* duplicate output parameters at the end for the expected values */
267*5273c5e4Smrg for (j = 0; j < param->nbout; j++)
268*5273c5e4Smrg {
269*5273c5e4Smrg MPC_ASSERT (nbout + nbin + j < PARAMETER_ARRAY_SIZE);
270*5273c5e4Smrg param->T[nbout + nbin + j] = param->T[j];
271*5273c5e4Smrg }
272*5273c5e4Smrg
273*5273c5e4Smrg close_datafile(&datafile_context);
274*5273c5e4Smrg }
275