xref: /qemu/qapi/qapi-visit-core.c (revision 60390d2dc85ffade8981ca41e02335cb07353a6d)
12345c77cSMichael Roth /*
22345c77cSMichael Roth  * Core Definitions for QAPI Visitor Classes
32345c77cSMichael Roth  *
47c91aabdSEric Blake  * Copyright (C) 2012-2016 Red Hat, Inc.
52345c77cSMichael Roth  * Copyright IBM, Corp. 2011
62345c77cSMichael Roth  *
72345c77cSMichael Roth  * Authors:
82345c77cSMichael Roth  *  Anthony Liguori   <aliguori@us.ibm.com>
92345c77cSMichael Roth  *
102345c77cSMichael Roth  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
112345c77cSMichael Roth  * See the COPYING.LIB file in the top-level directory.
122345c77cSMichael Roth  *
132345c77cSMichael Roth  */
142345c77cSMichael Roth 
15cbf21151SPeter Maydell #include "qemu/osdep.h"
16da34e65cSMarkus Armbruster #include "qapi/error.h"
1779ee7df8SPaolo Bonzini #include "qemu-common.h"
1869dd62dfSKevin Wolf #include "qapi/qmp/qobject.h"
197b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h"
207b1b5d19SPaolo Bonzini #include "qapi/visitor.h"
217b1b5d19SPaolo Bonzini #include "qapi/visitor-impl.h"
22ebfd93b6SDaniel P. Berrange #include "trace.h"
232345c77cSMichael Roth 
243b098d56SEric Blake void visit_complete(Visitor *v, void *opaque)
253b098d56SEric Blake {
263b098d56SEric Blake     assert(v->type != VISITOR_OUTPUT || v->complete);
27ebfd93b6SDaniel P. Berrange     trace_visit_complete(v, opaque);
283b098d56SEric Blake     if (v->complete) {
293b098d56SEric Blake         v->complete(v, opaque);
303b098d56SEric Blake     }
313b098d56SEric Blake }
323b098d56SEric Blake 
332c0ef9f4SEric Blake void visit_free(Visitor *v)
342c0ef9f4SEric Blake {
35ebfd93b6SDaniel P. Berrange     trace_visit_free(v);
362c0ef9f4SEric Blake     if (v) {
372c0ef9f4SEric Blake         v->free(v);
382c0ef9f4SEric Blake     }
392c0ef9f4SEric Blake }
402c0ef9f4SEric Blake 
4151e72bc1SEric Blake void visit_start_struct(Visitor *v, const char *name, void **obj,
42337283dfSEric Blake                         size_t size, Error **errp)
432345c77cSMichael Roth {
44e58d695eSEric Blake     Error *err = NULL;
45e58d695eSEric Blake 
46ebfd93b6SDaniel P. Berrange     trace_visit_start_struct(v, name, obj, size);
47adfb264cSEric Blake     if (obj) {
48adfb264cSEric Blake         assert(size);
49a15fcc3cSEric Blake         assert(!(v->type & VISITOR_OUTPUT) || *obj);
50adfb264cSEric Blake     }
51e58d695eSEric Blake     v->start_struct(v, name, obj, size, &err);
52a15fcc3cSEric Blake     if (obj && (v->type & VISITOR_INPUT)) {
53e58d695eSEric Blake         assert(!err != !*obj);
54e58d695eSEric Blake     }
55e58d695eSEric Blake     error_propagate(errp, err);
562345c77cSMichael Roth }
572345c77cSMichael Roth 
5815c2f669SEric Blake void visit_check_struct(Visitor *v, Error **errp)
592345c77cSMichael Roth {
60ebfd93b6SDaniel P. Berrange     trace_visit_check_struct(v);
6115c2f669SEric Blake     if (v->check_struct) {
6215c2f669SEric Blake         v->check_struct(v, errp);
6315c2f669SEric Blake     }
6415c2f669SEric Blake }
6515c2f669SEric Blake 
661158bb2aSEric Blake void visit_end_struct(Visitor *v, void **obj)
6715c2f669SEric Blake {
68ebfd93b6SDaniel P. Berrange     trace_visit_end_struct(v, obj);
691158bb2aSEric Blake     v->end_struct(v, obj);
702345c77cSMichael Roth }
712345c77cSMichael Roth 
72d9f62ddeSEric Blake void visit_start_list(Visitor *v, const char *name, GenericList **list,
73d9f62ddeSEric Blake                       size_t size, Error **errp)
742345c77cSMichael Roth {
75d9f62ddeSEric Blake     Error *err = NULL;
76d9f62ddeSEric Blake 
77d9f62ddeSEric Blake     assert(!list || size >= sizeof(GenericList));
78ebfd93b6SDaniel P. Berrange     trace_visit_start_list(v, name, list, size);
79d9f62ddeSEric Blake     v->start_list(v, name, list, size, &err);
80a15fcc3cSEric Blake     if (list && (v->type & VISITOR_INPUT)) {
81d9f62ddeSEric Blake         assert(!(err && *list));
82d9f62ddeSEric Blake     }
83d9f62ddeSEric Blake     error_propagate(errp, err);
842345c77cSMichael Roth }
852345c77cSMichael Roth 
86d9f62ddeSEric Blake GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
872345c77cSMichael Roth {
88d9f62ddeSEric Blake     assert(tail && size >= sizeof(GenericList));
89ebfd93b6SDaniel P. Berrange     trace_visit_next_list(v, tail, size);
90d9f62ddeSEric Blake     return v->next_list(v, tail, size);
912345c77cSMichael Roth }
922345c77cSMichael Roth 
93a4a1c70dSMarkus Armbruster void visit_check_list(Visitor *v, Error **errp)
94a4a1c70dSMarkus Armbruster {
95a4a1c70dSMarkus Armbruster     trace_visit_check_list(v);
96a4a1c70dSMarkus Armbruster     if (v->check_list) {
97a4a1c70dSMarkus Armbruster         v->check_list(v, errp);
98a4a1c70dSMarkus Armbruster     }
99a4a1c70dSMarkus Armbruster }
100a4a1c70dSMarkus Armbruster 
1011158bb2aSEric Blake void visit_end_list(Visitor *v, void **obj)
1022345c77cSMichael Roth {
103ebfd93b6SDaniel P. Berrange     trace_visit_end_list(v, obj);
1041158bb2aSEric Blake     v->end_list(v, obj);
1052345c77cSMichael Roth }
1062345c77cSMichael Roth 
107dbf11922SEric Blake void visit_start_alternate(Visitor *v, const char *name,
108dbf11922SEric Blake                            GenericAlternate **obj, size_t size,
109*60390d2dSMarc-André Lureau                            Error **errp)
110dbf11922SEric Blake {
111e58d695eSEric Blake     Error *err = NULL;
112e58d695eSEric Blake 
113dbf11922SEric Blake     assert(obj && size >= sizeof(GenericAlternate));
114a15fcc3cSEric Blake     assert(!(v->type & VISITOR_OUTPUT) || *obj);
115*60390d2dSMarc-André Lureau     trace_visit_start_alternate(v, name, obj, size);
116dbf11922SEric Blake     if (v->start_alternate) {
117*60390d2dSMarc-André Lureau         v->start_alternate(v, name, obj, size, &err);
118dbf11922SEric Blake     }
119a15fcc3cSEric Blake     if (v->type & VISITOR_INPUT) {
120e58d695eSEric Blake         assert(v->start_alternate && !err != !*obj);
121e58d695eSEric Blake     }
122e58d695eSEric Blake     error_propagate(errp, err);
123dbf11922SEric Blake }
124dbf11922SEric Blake 
1251158bb2aSEric Blake void visit_end_alternate(Visitor *v, void **obj)
126dbf11922SEric Blake {
127ebfd93b6SDaniel P. Berrange     trace_visit_end_alternate(v, obj);
128dbf11922SEric Blake     if (v->end_alternate) {
1291158bb2aSEric Blake         v->end_alternate(v, obj);
130dbf11922SEric Blake     }
131dbf11922SEric Blake }
132dbf11922SEric Blake 
13351e72bc1SEric Blake bool visit_optional(Visitor *v, const char *name, bool *present)
1342345c77cSMichael Roth {
135ebfd93b6SDaniel P. Berrange     trace_visit_optional(v, name, present);
136297a3646SMarkus Armbruster     if (v->optional) {
1370b2a0d6bSEric Blake         v->optional(v, name, present);
1382345c77cSMichael Roth     }
13929637a6eSEric Blake     return *present;
1402345c77cSMichael Roth }
1412345c77cSMichael Roth 
14268ab47e4SEric Blake bool visit_is_input(Visitor *v)
14368ab47e4SEric Blake {
14468ab47e4SEric Blake     return v->type == VISITOR_INPUT;
14568ab47e4SEric Blake }
14668ab47e4SEric Blake 
14751e72bc1SEric Blake void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
1482345c77cSMichael Roth {
149adfb264cSEric Blake     assert(obj);
150ebfd93b6SDaniel P. Berrange     trace_visit_type_int(v, name, obj);
1510b2a0d6bSEric Blake     v->type_int64(v, name, obj, errp);
1522345c77cSMichael Roth }
1532345c77cSMichael Roth 
15404e070d2SEric Blake static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
15504e070d2SEric Blake                              uint64_t max, const char *type, Error **errp)
15604e070d2SEric Blake {
15704e070d2SEric Blake     Error *err = NULL;
15804e070d2SEric Blake     uint64_t value = *obj;
15904e070d2SEric Blake 
1600b2a0d6bSEric Blake     v->type_uint64(v, name, &value, &err);
16104e070d2SEric Blake     if (err) {
16204e070d2SEric Blake         error_propagate(errp, err);
16304e070d2SEric Blake     } else if (value > max) {
16404e070d2SEric Blake         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
16504e070d2SEric Blake                    name ? name : "null", type);
16604e070d2SEric Blake     } else {
16704e070d2SEric Blake         *obj = value;
16804e070d2SEric Blake     }
16904e070d2SEric Blake }
17004e070d2SEric Blake 
17151e72bc1SEric Blake void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
17251e72bc1SEric Blake                       Error **errp)
1734e27e819SMichael Roth {
174ebfd93b6SDaniel P. Berrange     uint64_t value;
175ebfd93b6SDaniel P. Berrange 
176ebfd93b6SDaniel P. Berrange     trace_visit_type_uint8(v, name, obj);
177ebfd93b6SDaniel P. Berrange     value = *obj;
17804e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
1794e27e819SMichael Roth     *obj = value;
1804e27e819SMichael Roth }
1814e27e819SMichael Roth 
18251e72bc1SEric Blake void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
18304e070d2SEric Blake                        Error **errp)
1844e27e819SMichael Roth {
185ebfd93b6SDaniel P. Berrange     uint64_t value;
186ebfd93b6SDaniel P. Berrange 
187ebfd93b6SDaniel P. Berrange     trace_visit_type_uint16(v, name, obj);
188ebfd93b6SDaniel P. Berrange     value = *obj;
18904e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
1904e27e819SMichael Roth     *obj = value;
1914e27e819SMichael Roth }
1924e27e819SMichael Roth 
19351e72bc1SEric Blake void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
19404e070d2SEric Blake                        Error **errp)
1954e27e819SMichael Roth {
196ebfd93b6SDaniel P. Berrange     uint64_t value;
197ebfd93b6SDaniel P. Berrange 
198ebfd93b6SDaniel P. Berrange     trace_visit_type_uint32(v, name, obj);
199ebfd93b6SDaniel P. Berrange     value = *obj;
20004e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
2014e27e819SMichael Roth     *obj = value;
2024e27e819SMichael Roth }
2034e27e819SMichael Roth 
20451e72bc1SEric Blake void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
20504e070d2SEric Blake                        Error **errp)
2064e27e819SMichael Roth {
207adfb264cSEric Blake     assert(obj);
208ebfd93b6SDaniel P. Berrange     trace_visit_type_uint64(v, name, obj);
2090b2a0d6bSEric Blake     v->type_uint64(v, name, obj, errp);
2104e27e819SMichael Roth }
2114e27e819SMichael Roth 
21204e070d2SEric Blake static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
21304e070d2SEric Blake                             int64_t min, int64_t max, const char *type,
21404e070d2SEric Blake                             Error **errp)
2154e27e819SMichael Roth {
21604e070d2SEric Blake     Error *err = NULL;
21704e070d2SEric Blake     int64_t value = *obj;
218297a3646SMarkus Armbruster 
2190b2a0d6bSEric Blake     v->type_int64(v, name, &value, &err);
22004e070d2SEric Blake     if (err) {
22104e070d2SEric Blake         error_propagate(errp, err);
22204e070d2SEric Blake     } else if (value < min || value > max) {
223c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
22404e070d2SEric Blake                    name ? name : "null", type);
22504e070d2SEric Blake     } else {
2264e27e819SMichael Roth         *obj = value;
2274e27e819SMichael Roth     }
2284e27e819SMichael Roth }
2294e27e819SMichael Roth 
23051e72bc1SEric Blake void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
23104e070d2SEric Blake {
232ebfd93b6SDaniel P. Berrange     int64_t value;
233ebfd93b6SDaniel P. Berrange 
234ebfd93b6SDaniel P. Berrange     trace_visit_type_int8(v, name, obj);
235ebfd93b6SDaniel P. Berrange     value = *obj;
23604e070d2SEric Blake     visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
23704e070d2SEric Blake     *obj = value;
23804e070d2SEric Blake }
23904e070d2SEric Blake 
24051e72bc1SEric Blake void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
24151e72bc1SEric Blake                       Error **errp)
2424e27e819SMichael Roth {
243ebfd93b6SDaniel P. Berrange     int64_t value;
244ebfd93b6SDaniel P. Berrange 
245ebfd93b6SDaniel P. Berrange     trace_visit_type_int16(v, name, obj);
246ebfd93b6SDaniel P. Berrange     value = *obj;
24704e070d2SEric Blake     visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
2484e27e819SMichael Roth     *obj = value;
2494e27e819SMichael Roth }
2504e27e819SMichael Roth 
25151e72bc1SEric Blake void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
25251e72bc1SEric Blake                       Error **errp)
2534e27e819SMichael Roth {
254ebfd93b6SDaniel P. Berrange     int64_t value;
255ebfd93b6SDaniel P. Berrange 
256ebfd93b6SDaniel P. Berrange     trace_visit_type_int32(v, name, obj);
257ebfd93b6SDaniel P. Berrange     value = *obj;
25804e070d2SEric Blake     visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
2594e27e819SMichael Roth     *obj = value;
2604e27e819SMichael Roth }
2614e27e819SMichael Roth 
26251e72bc1SEric Blake void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
26351e72bc1SEric Blake                       Error **errp)
2644e27e819SMichael Roth {
265adfb264cSEric Blake     assert(obj);
266ebfd93b6SDaniel P. Berrange     trace_visit_type_int64(v, name, obj);
2670b2a0d6bSEric Blake     v->type_int64(v, name, obj, errp);
2684e27e819SMichael Roth }
2694e27e819SMichael Roth 
27051e72bc1SEric Blake void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
27151e72bc1SEric Blake                      Error **errp)
272092705d4SLaszlo Ersek {
273adfb264cSEric Blake     assert(obj);
274ebfd93b6SDaniel P. Berrange     trace_visit_type_size(v, name, obj);
275b8877962SVasilis Liaskovitis     if (v->type_size) {
2760b2a0d6bSEric Blake         v->type_size(v, name, obj, errp);
277b8877962SVasilis Liaskovitis     } else {
2780b2a0d6bSEric Blake         v->type_uint64(v, name, obj, errp);
279b8877962SVasilis Liaskovitis     }
280092705d4SLaszlo Ersek }
281092705d4SLaszlo Ersek 
28251e72bc1SEric Blake void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
2832345c77cSMichael Roth {
284adfb264cSEric Blake     assert(obj);
285ebfd93b6SDaniel P. Berrange     trace_visit_type_bool(v, name, obj);
2860b2a0d6bSEric Blake     v->type_bool(v, name, obj, errp);
2872345c77cSMichael Roth }
2882345c77cSMichael Roth 
28951e72bc1SEric Blake void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
2902345c77cSMichael Roth {
291e58d695eSEric Blake     Error *err = NULL;
292e58d695eSEric Blake 
293e58d695eSEric Blake     assert(obj);
294adfb264cSEric Blake     /* TODO: Fix callers to not pass NULL when they mean "", so that we
295adfb264cSEric Blake      * can enable:
296a15fcc3cSEric Blake     assert(!(v->type & VISITOR_OUTPUT) || *obj);
297adfb264cSEric Blake      */
298ebfd93b6SDaniel P. Berrange     trace_visit_type_str(v, name, obj);
299e58d695eSEric Blake     v->type_str(v, name, obj, &err);
300a15fcc3cSEric Blake     if (v->type & VISITOR_INPUT) {
301e58d695eSEric Blake         assert(!err != !*obj);
302e58d695eSEric Blake     }
303e58d695eSEric Blake     error_propagate(errp, err);
3042345c77cSMichael Roth }
3052345c77cSMichael Roth 
30651e72bc1SEric Blake void visit_type_number(Visitor *v, const char *name, double *obj,
30751e72bc1SEric Blake                        Error **errp)
3082345c77cSMichael Roth {
309adfb264cSEric Blake     assert(obj);
310ebfd93b6SDaniel P. Berrange     trace_visit_type_number(v, name, obj);
3110b2a0d6bSEric Blake     v->type_number(v, name, obj, errp);
3122345c77cSMichael Roth }
3130f71a1e0SPaolo Bonzini 
31451e72bc1SEric Blake void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
31528770e05SMarkus Armbruster {
316e58d695eSEric Blake     Error *err = NULL;
317e58d695eSEric Blake 
318e58d695eSEric Blake     assert(obj);
319adfb264cSEric Blake     assert(v->type != VISITOR_OUTPUT || *obj);
320ebfd93b6SDaniel P. Berrange     trace_visit_type_any(v, name, obj);
321e58d695eSEric Blake     v->type_any(v, name, obj, &err);
322e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
323e58d695eSEric Blake         assert(!err != !*obj);
324e58d695eSEric Blake     }
325e58d695eSEric Blake     error_propagate(errp, err);
32628770e05SMarkus Armbruster }
32728770e05SMarkus Armbruster 
3283bc97fd5SEric Blake void visit_type_null(Visitor *v, const char *name, Error **errp)
3293bc97fd5SEric Blake {
330ebfd93b6SDaniel P. Berrange     trace_visit_type_null(v, name);
3313bc97fd5SEric Blake     v->type_null(v, name, errp);
3323bc97fd5SEric Blake }
3333bc97fd5SEric Blake 
334983f52d4SEric Blake static void output_type_enum(Visitor *v, const char *name, int *obj,
335337283dfSEric Blake                              const char *const strings[], Error **errp)
3360f71a1e0SPaolo Bonzini {
3370f71a1e0SPaolo Bonzini     int i = 0;
3380f71a1e0SPaolo Bonzini     int value = *obj;
3390f71a1e0SPaolo Bonzini     char *enum_str;
3400f71a1e0SPaolo Bonzini 
3410f71a1e0SPaolo Bonzini     while (strings[i++] != NULL);
3420f71a1e0SPaolo Bonzini     if (value < 0 || value >= i - 1) {
343c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
3440f71a1e0SPaolo Bonzini         return;
3450f71a1e0SPaolo Bonzini     }
3460f71a1e0SPaolo Bonzini 
3470f71a1e0SPaolo Bonzini     enum_str = (char *)strings[value];
34851e72bc1SEric Blake     visit_type_str(v, name, &enum_str, errp);
3490f71a1e0SPaolo Bonzini }
3500f71a1e0SPaolo Bonzini 
351983f52d4SEric Blake static void input_type_enum(Visitor *v, const char *name, int *obj,
352337283dfSEric Blake                             const char *const strings[], Error **errp)
3530f71a1e0SPaolo Bonzini {
354297a3646SMarkus Armbruster     Error *local_err = NULL;
3550f71a1e0SPaolo Bonzini     int64_t value = 0;
3560f71a1e0SPaolo Bonzini     char *enum_str;
3570f71a1e0SPaolo Bonzini 
35851e72bc1SEric Blake     visit_type_str(v, name, &enum_str, &local_err);
359297a3646SMarkus Armbruster     if (local_err) {
360297a3646SMarkus Armbruster         error_propagate(errp, local_err);
3610f71a1e0SPaolo Bonzini         return;
3620f71a1e0SPaolo Bonzini     }
3630f71a1e0SPaolo Bonzini 
3640f71a1e0SPaolo Bonzini     while (strings[value] != NULL) {
3650f71a1e0SPaolo Bonzini         if (strcmp(strings[value], enum_str) == 0) {
3660f71a1e0SPaolo Bonzini             break;
3670f71a1e0SPaolo Bonzini         }
3680f71a1e0SPaolo Bonzini         value++;
3690f71a1e0SPaolo Bonzini     }
3700f71a1e0SPaolo Bonzini 
3710f71a1e0SPaolo Bonzini     if (strings[value] == NULL) {
372c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
3730f71a1e0SPaolo Bonzini         g_free(enum_str);
3740f71a1e0SPaolo Bonzini         return;
3750f71a1e0SPaolo Bonzini     }
3760f71a1e0SPaolo Bonzini 
3770f71a1e0SPaolo Bonzini     g_free(enum_str);
3780f71a1e0SPaolo Bonzini     *obj = value;
3790f71a1e0SPaolo Bonzini }
380983f52d4SEric Blake 
381983f52d4SEric Blake void visit_type_enum(Visitor *v, const char *name, int *obj,
382983f52d4SEric Blake                      const char *const strings[], Error **errp)
383983f52d4SEric Blake {
384adfb264cSEric Blake     assert(obj && strings);
3856514532fSStefan Hajnoczi     trace_visit_type_enum(v, name, obj);
386a15fcc3cSEric Blake     switch (v->type) {
387a15fcc3cSEric Blake     case VISITOR_INPUT:
388983f52d4SEric Blake         input_type_enum(v, name, obj, strings, errp);
389a15fcc3cSEric Blake         break;
390a15fcc3cSEric Blake     case VISITOR_OUTPUT:
391983f52d4SEric Blake         output_type_enum(v, name, obj, strings, errp);
392a15fcc3cSEric Blake         break;
393a15fcc3cSEric Blake     case VISITOR_CLONE:
394a15fcc3cSEric Blake         /* nothing further to do, scalar value was already copied by
395a15fcc3cSEric Blake          * g_memdup() during visit_start_*() */
396a15fcc3cSEric Blake         break;
397a15fcc3cSEric Blake     case VISITOR_DEALLOC:
398a15fcc3cSEric Blake         /* nothing to deallocate for a scalar */
399a15fcc3cSEric Blake         break;
400983f52d4SEric Blake     }
401983f52d4SEric Blake }
402