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