Fixed license declaration at spec file
[platform/upstream/gdbm.git] / src / datconv.c
1 /* This file is part of GDBM, the GNU data base manager.
2    Copyright (C) 1990, 1991, 1993, 2007, 2011, 2013 Free Software Foundation,
3    Inc.
4
5    GDBM is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3, or (at your option)
8    any later version.
9
10    GDBM is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with GDBM. If not, see <http://www.gnu.org/licenses/>.    */
17
18 #include "gdbmtool.h"
19
20 #define DEFFMT(name, type, fmt)                 \
21 static int                                      \
22 name (FILE *fp, void *ptr, int size)            \
23 {                                               \
24   fprintf (fp, fmt, *(type*) ptr);              \
25   return size;                                  \
26 }
27
28 DEFFMT (f_char, char, "%c")
29 DEFFMT (f_short, short, "%hd")
30 DEFFMT (f_ushort, unsigned short, "%hu")
31 DEFFMT (f_int, int, "%d")
32 DEFFMT (f_uint, unsigned, "%u")
33 DEFFMT (f_long, long, "%ld")
34 DEFFMT (f_ulong, unsigned long, "%lu")
35 DEFFMT (f_llong, long long, "%lld")
36 DEFFMT (f_ullong, unsigned long long, "%llu")
37 DEFFMT (f_float, float, "%f")
38 DEFFMT (f_double, double, "%e")
39
40 static int
41 f_stringz (FILE *fp, void *ptr, int size)
42 {
43   int sz;
44   char *s;
45   
46   for (sz = 1, s = ptr; *s; s++, sz++)
47     {
48       int c;
49       
50       if (isprint (*s))
51         fputc (*s, fp);
52       else if ((c = escape (*s)))
53         fprintf (fp, "\\%c", c);
54       else
55         fprintf (fp, "\\%03o", *s);
56     }
57   return sz;
58 }
59
60 static int
61 f_string (FILE *fp, void *ptr, int size)
62 {
63   int sz;
64   char *s;
65   
66   for (sz = 0, s = ptr; sz < size; s++, sz++)
67     {
68       int c;
69       
70       if (isprint (*s))
71         fputc (*s, fp);
72       else if ((c = escape (*s)))
73         fprintf (fp, "\\%c", c);
74       else
75         fprintf (fp, "\\%03o", *s);
76     }
77   return sz;
78 }
79 \f
80 int
81 s_char (struct xdatum *xd, char *str)
82 {
83   xd_store (xd, str, 1);
84   return 0;
85 }
86
87 #define DEFNSCAN(name, type, temptype, strto)   \
88 int                                             \
89 name (struct xdatum *xd, char *str)             \
90 {                                               \
91   temptype n;                                   \
92   type t;                                       \
93   char *p;                                      \
94                                                 \
95   errno = 0;                                    \
96   n = strto (str, &p, 0);                       \
97   if (*p)                                       \
98     return 1;                                   \
99   if (errno == ERANGE || (t = n) != n)          \
100     return 1;                                   \
101   xd_store (xd, &n, sizeof (n));                \
102   return 0;                                     \
103 }
104
105 DEFNSCAN(s_short, short, long, strtol);
106 DEFNSCAN(s_ushort, unsigned short, unsigned long, strtoul);
107 DEFNSCAN(s_int, int, long, strtol)
108 DEFNSCAN(s_uint, unsigned, unsigned long, strtol)
109 DEFNSCAN(s_long, long, long, strtoul)
110 DEFNSCAN(s_ulong, unsigned long, unsigned long, strtoul)
111 DEFNSCAN(s_llong, long long, long long, strtoll)
112 DEFNSCAN(s_ullong, unsigned long long, unsigned long long, strtoull)
113
114 int
115 s_double (struct xdatum *xd, char *str)
116 {
117   double d;
118   char *p;
119   
120   errno = 0;
121   d = strtod (str, &p);
122   if (errno || *p)
123     return 1;
124   xd_store (xd, &d, sizeof (d));
125   return 0;
126 }
127
128 int
129 s_float (struct xdatum *xd, char *str)
130 {
131   float d;
132   char *p;
133   
134   errno = 0;
135   d = strtod (str, &p);
136   if (errno || *p)
137     return 1;
138   xd_store (xd, &d, sizeof (d));
139   return 0;
140 }
141
142 int
143 s_stringz (struct xdatum *xd, char *str)
144 {
145   xd_store (xd, str, strlen (str) + 1);
146   return 0;
147 }
148
149 int
150 s_string (struct xdatum *xd, char *str)
151 {
152   xd_store (xd, str, strlen (str));
153   return 0;
154 }
155
156 static struct datadef datatab[] = {
157   { "char",     sizeof(char),      f_char, s_char },
158   { "short",    sizeof(short),     f_short, s_short },
159   { "ushort",   sizeof(unsigned short), f_ushort, s_ushort },
160   { "int",      sizeof(int),       f_int, s_int  },
161   { "unsigned", sizeof(unsigned),  f_uint, s_uint },
162   { "uint",     sizeof(unsigned),  f_uint, s_uint },
163   { "long",     sizeof(long),      f_long, s_long },
164   { "ulong",    sizeof(unsigned long),     f_ulong, s_ulong },
165   { "llong",    sizeof(long long), f_llong, s_llong },
166   { "ullong",   sizeof(unsigned long long), f_ullong, s_ullong },
167   { "float",    sizeof(float),     f_float, s_float }, 
168   { "double",   sizeof(double),    f_double, s_double },
169   { "stringz",  0, f_stringz, s_stringz },
170   { "string",   0, f_string, s_string },
171   { NULL }
172 };
173
174 struct datadef *
175 datadef_lookup (const char *name)
176 {
177   struct datadef *p;
178
179   for (p = datatab; p->name; p++)
180     if (strcmp (p->name, name) == 0)
181       return p;
182   return NULL;
183 }
184 \f
185 struct dsegm *
186 dsegm_new (int type)
187 {
188   struct dsegm *p = emalloc (sizeof (*p));
189   p->next = NULL;
190   p->type = type;
191   return p;
192 }
193
194 struct dsegm *
195 dsegm_new_field (struct datadef *type, char *id, int dim)
196 {
197   struct dsegm *p = dsegm_new (FDEF_FLD);
198   p->v.field.type = type;
199   p->v.field.name = id;
200   p->v.field.dim = dim;
201   return p;
202 }
203
204 void
205 dsegm_free_list (struct dsegm *dp)
206 {
207   while (dp)
208     {
209       struct dsegm *next = dp->next;
210       free (dp);
211       dp = next;
212     }
213 }
214
215 void
216 datum_format (FILE *fp, datum const *dat, struct dsegm *ds)
217 {
218   int off = 0;
219   char *delim[2];
220   int first_field = 1;
221   
222   if (!ds)
223     {
224       fprintf (fp, "%.*s\n", dat->dsize, dat->dptr);
225       return;
226     }
227
228   if (variable_get ("delim1", VART_STRING, (void*) &delim[0]))
229     abort ();
230   if (variable_get ("delim2", VART_STRING, (void*) &delim[1]))
231     abort ();
232   
233   for (; ds && off <= dat->dsize; ds = ds->next)
234     {
235       switch (ds->type)
236         {
237         case FDEF_FLD:
238           if (!first_field)
239             fwrite (delim[1], strlen (delim[1]), 1, fp);
240           if (ds->v.field.name)
241             fprintf (fp, "%s=", ds->v.field.name);
242           if (ds->v.field.dim > 1)
243             fprintf (fp, "{ ");
244           if (ds->v.field.type->format)
245             {
246               int i, n;
247
248               for (i = 0; i < ds->v.field.dim; i++)
249                 {
250                   if (i)
251                     fwrite (delim[0], strlen (delim[0]), 1, fp);
252                   if (off + ds->v.field.type->size > dat->dsize)
253                     {
254                       fprintf (fp, _("(not enough data)"));
255                       off += dat->dsize;
256                       break;
257                     }
258                   else
259                     {
260                       n = ds->v.field.type->format (fp,
261                                                     (char*) dat->dptr + off,
262                                                     ds->v.field.type->size ?
263                                                       ds->v.field.type->size :
264                                                       dat->dsize - off);
265                       off += n;
266                     }
267                 }
268             }
269           if (ds->v.field.dim > 1)
270             fprintf (fp, " }");
271           first_field = 0;
272           break;
273           
274         case FDEF_OFF:
275           off = ds->v.n;
276           break;
277           
278         case FDEF_PAD:
279           off += ds->v.n;
280           break;
281         }
282     }
283 }
284 \f
285 struct xdatum
286 {
287   char *dptr;
288   size_t dsize;
289   size_t dmax;
290   int off;
291 };
292
293 void
294 xd_expand (struct xdatum *xd, size_t size)
295 {
296   if (xd->dmax < size)
297     {
298       xd->dptr = erealloc (xd->dptr, size);
299       memset (xd->dptr + xd->dmax, 0, size - xd->dmax);
300       xd->dmax = size;
301     }
302 }
303   
304 void
305 xd_store (struct xdatum *xd, void *val, size_t size)
306 {
307   xd_expand (xd, xd->off + size);
308   memcpy (xd->dptr + xd->off, val, size);
309   xd->off += size;
310   if (xd->off > xd->dsize)
311     xd->dsize = xd->off;
312
313 \f
314 static int
315 datum_scan_notag (datum *dat, struct dsegm *ds, struct kvpair *kv)
316 {
317   struct xdatum xd;
318   int i;
319   struct slist *s;
320   int err = 0;
321   
322   memset (&xd, 0, sizeof (xd));
323   
324   for (; err == 0 && ds && kv; ds = ds->next, kv = kv->next)
325     {
326       if (kv->key)
327         {
328           lerror (&kv->loc,
329                        _("mixing tagged and untagged values is not allowed"));
330           err = 1;
331           break;
332         }
333       
334       switch (ds->type)
335         {
336         case FDEF_FLD:
337           if (!ds->v.field.type->scan)
338             abort ();
339
340           switch (kv->type)
341             {
342             case KV_STRING:
343               err = ds->v.field.type->scan (&xd, kv->val.s);
344               if (err)
345                 lerror (&kv->loc, _("cannot convert"));
346               break;
347               
348             case KV_LIST:
349               for (i = 0, s = kv->val.l; i < ds->v.field.dim && s;
350                    i++, s = s->next)
351                 {
352                   err = ds->v.field.type->scan (&xd, s->str);
353                   if (err)
354                     {
355                       lerror (&kv->loc,
356                                    _("cannot convert value #%d: %s"),
357                                    i, s->str);
358                       break;
359                     }
360                 }
361               /* FIXME: Warn if (s) -> "extra data" */
362             }                                 
363           break;
364
365         case FDEF_OFF:
366           xd_expand (&xd, ds->v.n);
367           xd.off = ds->v.n;
368           break;
369           
370         case FDEF_PAD:
371           xd_expand (&xd, xd.off + ds->v.n);
372           xd.off += ds->v.n;
373           break;
374         }
375     }
376
377   if (err)
378     {
379       free (xd.dptr);
380       return 1;
381     }
382
383   dat->dptr  = xd.dptr;
384   dat->dsize = xd.dsize;
385       
386   return 0;
387 }
388
389 static int
390 datum_scan_tag (datum *dat, struct dsegm *ds, struct kvpair *kv)
391 {
392   lerror (&kv->loc, "tagged values are not yet supported");
393   return 1;
394 }
395
396 int
397 datum_scan (datum *dat, struct dsegm *ds, struct kvpair *kv)
398 {
399   return (kv->key ? datum_scan_tag : datum_scan_notag) (dat, ds, kv);
400 }
401
402 void
403 dsprint (FILE *fp, int what, struct dsegm *ds)
404 {
405   static char *dsstr[] = { "key", "content" };
406   int delim;
407   
408   fprintf (fp, "define %s", dsstr[what]);
409   if (ds->next)
410     {
411       fprintf (fp, " {\n");
412       delim = '\t';
413     }
414   else
415     delim = ' ';
416   for (; ds; ds = ds->next)
417     {
418       switch (ds->type)
419         {
420         case FDEF_FLD:
421           fprintf (fp, "%c%s", delim, ds->v.field.type->name);
422           if (ds->v.field.name)
423             fprintf (fp, " %s", ds->v.field.name);
424           if (ds->v.field.dim > 1)
425             fprintf (fp, "[%d]", ds->v.field.dim);
426           break;
427           
428         case FDEF_OFF:
429           fprintf (fp, "%coffset %d", delim, ds->v.n);
430           break;
431
432         case FDEF_PAD:
433           fprintf (fp, "%cpad %d", delim, ds->v.n);
434           break;
435         }
436       if (ds->next)
437         fputc (',', fp);
438       fputc ('\n', fp);
439     }
440   if (delim == '\t')
441     fputs ("}\n", fp);
442 }