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