Home | History | Annotate | Download | only in nine
      1 /*
      2  * Copyright 2016 Patrick Rudolph <siro (at) das-labor.org>
      3  *
      4  * Permission is hereby granted, free of charge, f, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, f, copy, modify, merge, f, publish, distribute, f, sub
      8  * license, f, and/or sell copies of the Software, f, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISe, f, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
     22 
     23 /* get number of arguments with __NARG__ */
     24 #define __NARG__(...)  __NARG_I_(__VA_ARGS__,__RSEQ_N())
     25 #define __NARG_I_(...) __ARG_N(__VA_ARGS__)
     26 #define __ARG_N( \
     27       _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
     28      _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
     29      _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
     30      _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
     31      _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
     32      _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
     33      _61,_62,_63,N,...) N
     34 #define __RSEQ_N() \
     35      63,62,61,60,                   \
     36      59,58,57,56,55,54,53,52,51,50, \
     37      49,48,47,46,45,44,43,42,41,40, \
     38      39,38,37,36,35,34,33,32,31,30, \
     39      29,28,27,26,25,24,23,22,21,20, \
     40      19,18,17,16,15,14,13,12,11,10, \
     41      9,8,7,6,5,4,3,2,1,0
     42 
     43 
     44 #define _args_for_bypass_1(a) a
     45 #define _args_for_bypass_7(a, b, c, d, e, f, g) ,g
     46 #define _args_for_bypass_14(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_7(__VA_ARGS__)
     47 #define _args_for_bypass_21(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_14(__VA_ARGS__)
     48 #define _args_for_bypass_28(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_21(__VA_ARGS__)
     49 #define _args_for_bypass_35(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_28(__VA_ARGS__)
     50 #define _args_for_bypass_42(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_35(__VA_ARGS__)
     51 #define _args_for_bypass_49(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_42(__VA_ARGS__)
     52 #define _args_for_bypass_56(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_49(__VA_ARGS__)
     53 #define _args_for_bypass_63(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_56(__VA_ARGS__)
     54 #define _args_for_bypass_70(a, b, c, d, e, f, g, ...) ,g _args_for_bypass_63(__VA_ARGS__)
     55 
     56 #define _GFUNC_(n) _args_for_bypass_##n
     57 #define _GFUNC(n) _GFUNC_(n)
     58 
     59 #define ARGS_FOR_BYPASS(...) _GFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
     60 
     61 #define _args_for_mem_1(a) a;
     62 #define _args_for_mem_7(a, b, c, d, e, f, g) f;
     63 #define _args_for_mem_14(a, b, c, d, e, f, g, ...) f; _args_for_mem_7(__VA_ARGS__)
     64 #define _args_for_mem_21(a, b, c, d, e, f, g, ...) f; _args_for_mem_14(__VA_ARGS__)
     65 #define _args_for_mem_28(a, b, c, d, e, f, g, ...) f; _args_for_mem_21(__VA_ARGS__)
     66 #define _args_for_mem_35(a, b, c, d, e, f, g, ...) f; _args_for_mem_28(__VA_ARGS__)
     67 #define _args_for_mem_42(a, b, c, d, e, f, g, ...) f; _args_for_mem_35(__VA_ARGS__)
     68 #define _args_for_mem_49(a, b, c, d, e, f, g, ...) f; _args_for_mem_42(__VA_ARGS__)
     69 #define _args_for_mem_56(a, b, c, d, e, f, g, ...) f; _args_for_mem_49(__VA_ARGS__)
     70 #define _args_for_mem_63(a, b, c, d, e, f, g, ...) f; _args_for_mem_56(__VA_ARGS__)
     71 #define _args_for_mem_70(a, b, c, d, e, f, g, ...) f; _args_for_mem_63(__VA_ARGS__)
     72 
     73 #define _FFUNC_(n) _args_for_mem_##n
     74 #define _FFUNC(n) _FFUNC_(n)
     75 
     76 #define ARGS_FOR_MEM(...) _FFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
     77 
     78 #define _args_for_unbind_1(a) a;
     79 #define _args_for_unbind_7(a, b, c, d, e, f, g) e;
     80 #define _args_for_unbind_14(a, b, c, d, e, f, g, ...) e; _args_for_unbind_7(__VA_ARGS__)
     81 #define _args_for_unbind_21(a, b, c, d, e, f, g, ...) e; _args_for_unbind_14(__VA_ARGS__)
     82 #define _args_for_unbind_28(a, b, c, d, e, f, g, ...) e; _args_for_unbind_21(__VA_ARGS__)
     83 #define _args_for_unbind_35(a, b, c, d, e, f, g, ...) e; _args_for_unbind_28(__VA_ARGS__)
     84 #define _args_for_unbind_42(a, b, c, d, e, f, g, ...) e; _args_for_unbind_35(__VA_ARGS__)
     85 #define _args_for_unbind_49(a, b, c, d, e, f, g, ...) e; _args_for_unbind_42(__VA_ARGS__)
     86 #define _args_for_unbind_56(a, b, c, d, e, f, g, ...) e; _args_for_unbind_49(__VA_ARGS__)
     87 #define _args_for_unbind_63(a, b, c, d, e, f, g, ...) e; _args_for_unbind_56(__VA_ARGS__)
     88 #define _args_for_unbind_70(a, b, c, d, e, f, g, ...) e; _args_for_unbind_63(__VA_ARGS__)
     89 
     90 #define _EFUNC_(n) _args_for_unbind_##n
     91 #define _EFUNC(n) _EFUNC_(n)
     92 
     93 #define ARGS_FOR_UNBIND(...) _EFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
     94 
     95 #define _args_for_call_1(a) a
     96 #define _args_for_call_7(a, b, c, d, e, f, g) ,d
     97 #define _args_for_call_14(a, b, c, d, e, f, g, ...) ,d _args_for_call_7(__VA_ARGS__)
     98 #define _args_for_call_21(a, b, c, d, e, f, g, ...) ,d _args_for_call_14(__VA_ARGS__)
     99 #define _args_for_call_28(a, b, c, d, e, f, g, ...) ,d _args_for_call_21(__VA_ARGS__)
    100 #define _args_for_call_35(a, b, c, d, e, f, g, ...) ,d _args_for_call_28(__VA_ARGS__)
    101 #define _args_for_call_42(a, b, c, d, e, f, g, ...) ,d _args_for_call_35(__VA_ARGS__)
    102 #define _args_for_call_49(a, b, c, d, e, f, g, ...) ,d _args_for_call_42(__VA_ARGS__)
    103 #define _args_for_call_56(a, b, c, d, e, f, g, ...) ,d _args_for_call_49(__VA_ARGS__)
    104 #define _args_for_call_63(a, b, c, d, e, f, g, ...) ,d _args_for_call_56(__VA_ARGS__)
    105 #define _args_for_call_70(a, b, c, d, e, f, g, ...) ,d _args_for_call_63(__VA_ARGS__)
    106 
    107 #define _DFUNC_(n) _args_for_call_##n
    108 #define _DFUNC(n) _DFUNC_(n)
    109 
    110 #define ARGS_FOR_CALL(...) _DFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
    111 
    112 #define _args_for_decl_1(a) a
    113 #define _args_for_decl_7(a, b, c, d, e, f, g) ,c
    114 #define _args_for_decl_14(a, b, c, d, e, f, g, ...) ,c _args_for_decl_7(__VA_ARGS__)
    115 #define _args_for_decl_21(a, b, c, d, e, f, g, ...) ,c _args_for_decl_14(__VA_ARGS__)
    116 #define _args_for_decl_28(a, b, c, d, e, f, g, ...) ,c _args_for_decl_21(__VA_ARGS__)
    117 #define _args_for_decl_35(a, b, c, d, e, f, g, ...) ,c _args_for_decl_28(__VA_ARGS__)
    118 #define _args_for_decl_42(a, b, c, d, e, f, g, ...) ,c _args_for_decl_35(__VA_ARGS__)
    119 #define _args_for_decl_49(a, b, c, d, e, f, g, ...) ,c _args_for_decl_42(__VA_ARGS__)
    120 #define _args_for_decl_56(a, b, c, d, e, f, g, ...) ,c _args_for_decl_49(__VA_ARGS__)
    121 #define _args_for_decl_63(a, b, c, d, e, f, g, ...) ,c _args_for_decl_56(__VA_ARGS__)
    122 #define _args_for_decl_70(a, b, c, d, e, f, g, ...) ,c _args_for_decl_63(__VA_ARGS__)
    123 
    124 #define _CFUNC_(n) _args_for_decl_##n
    125 #define _CFUNC(n) _CFUNC_(n)
    126 
    127 #define ARGS_FOR_DECLARATION(...) _CFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
    128 
    129 #define _args_for_assign_1(a) a
    130 #define _args_for_assign_7(a, b, c, d, e, f, g) b;
    131 #define _args_for_assign_14(a, b, c, d, e, f, g, ...) b; _args_for_assign_7(__VA_ARGS__)
    132 #define _args_for_assign_21(a, b, c, d, e, f, g, ...) b; _args_for_assign_14(__VA_ARGS__)
    133 #define _args_for_assign_28(a, b, c, d, e, f, g, ...) b; _args_for_assign_21(__VA_ARGS__)
    134 #define _args_for_assign_35(a, b, c, d, e, f, g, ...) b; _args_for_assign_28(__VA_ARGS__)
    135 #define _args_for_assign_42(a, b, c, d, e, f, g, ...) b; _args_for_assign_35(__VA_ARGS__)
    136 #define _args_for_assign_49(a, b, c, d, e, f, g, ...) b; _args_for_assign_42(__VA_ARGS__)
    137 #define _args_for_assign_56(a, b, c, d, e, f, g, ...) b; _args_for_assign_49(__VA_ARGS__)
    138 #define _args_for_assign_63(a, b, c, d, e, f, g, ...) b; _args_for_assign_56(__VA_ARGS__)
    139 #define _args_for_assign_70(a, b, c, d, e, f, g, ...) b; _args_for_assign_63(__VA_ARGS__)
    140 
    141 #define _BFUNC_(n) _args_for_assign_##n
    142 #define _BFUNC(n) _BFUNC_(n)
    143 
    144 #define ARGS_FOR_ASSIGN(...) _BFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
    145 
    146 #define _args_for_struct_1(a) a;
    147 #define _args_for_struct_7(a, b, c, d, e, f, g) a;
    148 #define _args_for_struct_14(a, b, c, d, e, f, g, ...) a; _args_for_struct_7(__VA_ARGS__)
    149 #define _args_for_struct_21(a, b, c, d, e, f, g, ...) a; _args_for_struct_14(__VA_ARGS__)
    150 #define _args_for_struct_28(a, b, c, d, e, f, g, ...) a; _args_for_struct_21(__VA_ARGS__)
    151 #define _args_for_struct_35(a, b, c, d, e, f, g, ...) a; _args_for_struct_28(__VA_ARGS__)
    152 #define _args_for_struct_42(a, b, c, d, e, f, g, ...) a; _args_for_struct_35(__VA_ARGS__)
    153 #define _args_for_struct_49(a, b, c, d, e, f, g, ...) a; _args_for_struct_42(__VA_ARGS__)
    154 #define _args_for_struct_56(a, b, c, d, e, f, g, ...) a; _args_for_struct_49(__VA_ARGS__)
    155 #define _args_for_struct_63(a, b, c, d, e, f, g, ...) a; _args_for_struct_56(__VA_ARGS__)
    156 #define _args_for_struct_70(a, b, c, d, e, f, g, ...) a; _args_for_struct_63(__VA_ARGS__)
    157 
    158 #define _AFUNC_(n) _args_for_struct_##n
    159 #define _AFUNC(n) _AFUNC_(n)
    160 
    161 #define ARGS_FOR_STRUCT(...) _AFUNC(__NARG__(__VA_ARGS__)) (__VA_ARGS__)
    162 
    163 /* Serialization and deserialization */
    164 
    165 #define CSMT_ITEM_NO_WAIT(name, ...) \
    166 \
    167 struct s_##name##_private { \
    168     struct csmt_instruction instr; \
    169     ARGS_FOR_STRUCT( __VA_ARGS__ ) \
    170 }; \
    171 \
    172 static void \
    173 name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \
    174 \
    175 static int \
    176 name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \
    177 { \
    178     struct csmt_context *ctx = device->csmt_ctx; \
    179     struct s_##name##_private *args = (struct s_##name##_private *)instr; \
    180     \
    181     (void) args; \
    182     (void) ctx; \
    183     name##_priv( \
    184         device ARGS_FOR_CALL( __VA_ARGS__ ) \
    185     ); \
    186     ARGS_FOR_UNBIND( __VA_ARGS__ ) \
    187     return 0; \
    188 } \
    189 \
    190 void \
    191 name( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \
    192 { \
    193     struct csmt_context *ctx = device->csmt_ctx; \
    194     struct s_##name##_private *args; \
    195     unsigned memsize = sizeof(struct s_##name##_private); \
    196     unsigned memsize2 = 0; \
    197     \
    198     if (!device->csmt_active) { \
    199         name##_priv( \
    200             device ARGS_FOR_BYPASS( __VA_ARGS__ ) \
    201         ); \
    202         return; \
    203     } \
    204     ARGS_FOR_MEM ( __VA_ARGS__ ) \
    205     args = nine_queue_alloc(ctx->pool, memsize + memsize2); \
    206     assert(args); \
    207     args->instr.func = &name##_rx; \
    208     ARGS_FOR_ASSIGN( __VA_ARGS__ ) \
    209 } \
    210 \
    211 static void \
    212 name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) )
    213 
    214 #define CSMT_ITEM_NO_WAIT_WITH_COUNTER(name, ...) \
    215 \
    216 struct s_##name##_private { \
    217     struct csmt_instruction instr; \
    218     unsigned *counter; \
    219     ARGS_FOR_STRUCT( __VA_ARGS__ ) \
    220 }; \
    221 \
    222 static void \
    223 name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \
    224 \
    225 static int \
    226 name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \
    227 { \
    228     struct csmt_context *ctx = device->csmt_ctx; \
    229     struct s_##name##_private *args = (struct s_##name##_private *)instr; \
    230     \
    231     (void) args; \
    232     (void) ctx; \
    233     name##_priv( \
    234         device ARGS_FOR_CALL( __VA_ARGS__ ) \
    235     ); \
    236     p_atomic_dec(args->counter); \
    237     ARGS_FOR_UNBIND( __VA_ARGS__ ) \
    238     return 0; \
    239 } \
    240 \
    241 void \
    242 name( struct NineDevice9 *device, unsigned *counter ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \
    243 { \
    244     struct csmt_context *ctx = device->csmt_ctx; \
    245     struct s_##name##_private *args; \
    246     unsigned memsize = sizeof(struct s_##name##_private); \
    247     unsigned memsize2 = 0; \
    248     \
    249     if (!device->csmt_active) { \
    250         name##_priv( \
    251             device ARGS_FOR_BYPASS( __VA_ARGS__ ) \
    252         ); \
    253         return; \
    254     } \
    255     assert(counter); \
    256     p_atomic_inc(counter); \
    257     ARGS_FOR_MEM ( __VA_ARGS__ ) \
    258     args = nine_queue_alloc(ctx->pool, memsize + memsize2); \
    259     assert(args); \
    260     args->instr.func = &name##_rx; \
    261     args->counter = counter; \
    262     ARGS_FOR_ASSIGN( __VA_ARGS__ ) \
    263 } \
    264 \
    265 static void \
    266 name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) )
    267 
    268 #define CSMT_ITEM_DO_WAIT(name, ...) \
    269 \
    270 struct s_##name##_private { \
    271     struct csmt_instruction instr; \
    272     ARGS_FOR_STRUCT( __VA_ARGS__ ) \
    273 }; \
    274 static void \
    275 name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ); \
    276 \
    277 static int \
    278 name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr) \
    279 { \
    280     struct csmt_context *ctx = device->csmt_ctx; \
    281     struct s_##name##_private *args = (struct s_##name##_private *)instr; \
    282     \
    283     (void) args; \
    284     (void) ctx; \
    285     name##_priv( \
    286         device ARGS_FOR_CALL( __VA_ARGS__ ) \
    287     ); \
    288     ARGS_FOR_UNBIND( __VA_ARGS__ ) \
    289     return 1; \
    290 } \
    291 \
    292 void \
    293 name( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) ) \
    294 { \
    295     struct csmt_context *ctx = device->csmt_ctx; \
    296     struct s_##name##_private *args; \
    297     unsigned memsize = sizeof(struct s_##name##_private); \
    298     unsigned memsize2 = 0; \
    299     \
    300     if (!device->csmt_active) { \
    301         name##_priv( \
    302             device ARGS_FOR_BYPASS( __VA_ARGS__ ) \
    303         ); \
    304         return; \
    305     } \
    306     ARGS_FOR_MEM ( __VA_ARGS__ ) \
    307     args = nine_queue_alloc(ctx->pool, memsize + memsize2); \
    308     assert(args); \
    309     args->instr.func = &name##_rx; \
    310     ARGS_FOR_ASSIGN( __VA_ARGS__ ) \
    311     ctx->processed = FALSE; \
    312     nine_queue_flush(ctx->pool); \
    313     nine_csmt_wait_processed(ctx); \
    314 } \
    315 \
    316 static void \
    317 name##_priv( struct NineDevice9 *device ARGS_FOR_DECLARATION( __VA_ARGS__ ) )
    318 
    319 /* ARGS_FOR_STRUCT, ARGS_FOR_ASSIGN, ARGS_FOR_DECLARATION, ARGS_FOR_CALL, ARGS_FOR_UNBIND, ARGS_FOR_MEM, ARGS_FOR_BYPASS */
    320 #define ARG_VAL(x, y) \
    321         x _##y ; ,\
    322         args->_##y = y ; ,\
    323         x y ,\
    324         args->_##y ,\
    325         ,\
    326         ,\
    327         y
    328 
    329 #define ARG_REF(x, y) \
    330         x* _##y ; ,\
    331         args->_##y = y; ,\
    332         x *y ,\
    333         args->_##y ,\
    334         ,\
    335         ,\
    336         y
    337 
    338 #define ARG_COPY_REF(x, y) \
    339         x * _##y ; x __##y ; ,\
    340         if ( y ) { args->_##y = &args->__##y ; args->__##y = *y ; } else { args->_##y = NULL; } ,\
    341         const x *y ,\
    342         (const x *)args->_##y ,\
    343         ,\
    344         ,\
    345         (const x *)y
    346 
    347 #define ARG_BIND_REF(x, y) \
    348         x * _##y ,\
    349         if ( y ) \
    350             NineUnknown_Bind( (void *)y ); \
    351         args->_##y = y ; ,\
    352         x *y ,\
    353         args->_##y,\
    354         if (args->_##y) \
    355             NineUnknown_Unbind((void *)(args->_##y)); \
    356         args->_##y = NULL; ,\
    357         ,\
    358         y
    359 
    360 #define ARG_BIND_RES(x, y) \
    361         x * _##y ,\
    362         args->_##y = NULL; \
    363         if (y) \
    364             pipe_resource_reference(&args->_##y, y); ,\
    365         x *y ,\
    366         args->_##y ,\
    367         if (args->_##y) \
    368             pipe_resource_reference(&args->_##y, NULL); ,\
    369         ,\
    370         y
    371 
    372 #define ARG_MEM(x, y) \
    373         x * _##y ,\
    374         args->_##y = (void *)args + memsize;\
    375         memcpy(args->_##y, y, memsize2); ,\
    376         const x *y ,\
    377         (const x *)args->_##y ,\
    378         ,\
    379         ,\
    380         (const x *)y
    381 
    382 #define ARG_MEM_SIZE(x, y) \
    383         x _##y ,\
    384         args->_##y = y; ,\
    385         x y ,\
    386         args->_##y ,\
    387         ,\
    388         memsize2 = y, \
    389         y
    390 
    391 #define ARG_BIND_BLIT(x, y) \
    392         x _##y ,\
    393         memcpy(&args->_##y , y, sizeof(x)); \
    394         args->_##y.src.resource = NULL; \
    395         args->_##y.dst.resource = NULL; \
    396         pipe_resource_reference(&args->_##y.src.resource, y->src.resource); \
    397         pipe_resource_reference(&args->_##y.dst.resource, y->dst.resource);,\
    398         x *y ,\
    399         &args->_##y ,\
    400         pipe_resource_reference(&args->_##y.src.resource, NULL); \
    401         pipe_resource_reference(&args->_##y.dst.resource, NULL);,\
    402         ,\
    403         y
    404 
    405 #define ARG_BIND_BUF(x, y) \
    406         x _##y ,\
    407         memcpy(&args->_##y , y, sizeof(x)); \
    408         args->_##y.buffer = NULL; \
    409         pipe_resource_reference(&args->_##y.buffer, y->buffer); ,\
    410         x *y ,\
    411         &args->_##y ,\
    412         pipe_resource_reference(&args->_##y.buffer, NULL); ,\
    413         ,\
    414         y
    415 
    416 #define ARG_BIND_VIEW(x, y) \
    417         x * _##y ,\
    418         args->_##y = NULL; \
    419         if (y) \
    420             pipe_sampler_view_reference(&args->_##y, y); ,\
    421         x *y ,\
    422         args->_##y ,\
    423         if (args->_##y) \
    424             pipe_sampler_view_reference(&args->_##y, NULL); ,\
    425         ,\
    426         y
    427 
    428