kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

decls.c (18357B)


      1 #include <stdio.h>
      2 #include <string.h>
      3 
      4 #include "internal.h"
      5 
      6 int toy_parse_type_alias_decl(ToyParser* p) {
      7   KitSym name;
      8   KitCgTypeId base;
      9   if (!toy_parser_match(p, TOK_TYPE)) return 0;
     10   if (p->cur.kind != TOK_IDENT) {
     11     toy_error(p, p->cur.loc, "expected type alias name");
     12     return 0;
     13   }
     14   name = toy_tok_sym(p, p->cur);
     15   toy_parser_advance(p);
     16   if (!toy_parser_expect(p, TOK_EQ)) {
     17     toy_error(p, p->cur.loc, "expected '=' in type alias");
     18     return 0;
     19   }
     20   base = toy_parse_type(p);
     21   if (base == KIT_CG_TYPE_NONE) return 0;
     22   if (!toy_parser_expect(p, TOK_SEMI)) {
     23     toy_error(p, p->cur.loc, "expected ';' after type alias");
     24     return 0;
     25   }
     26   return toy_add_named_type(p, name, base, TOY_NAMED_ALIAS, base);
     27 }
     28 
     29 int toy_parse_record_decl(ToyParser* p) {
     30   KitSym name;
     31   KitCgFieldDesc* fields = NULL;
     32   ToyRecordFieldInfo* field_infos = NULL;
     33   size_t nfields = 0;
     34   size_t cap_fields = 0;
     35   size_t cap_field_infos = 0;
     36   KitCgTypeId type = KIT_CG_TYPE_NONE;
     37   ToyNamedType* named;
     38   int packed = 0;
     39   uint32_t record_align = 0;
     40   int ok = 0;
     41 
     42   if (!toy_parser_match(p, TOK_RECORD)) return 0;
     43   if (!toy_parse_record_attr_list(p, &packed, &record_align)) return 0;
     44   if (p->cur.kind != TOK_IDENT) {
     45     toy_error(p, p->cur.loc, "expected record name");
     46     return 0;
     47   }
     48   name = toy_tok_sym(p, p->cur);
     49   toy_parser_advance(p);
     50   named = toy_find_named_type(p, name);
     51   if (toy_parser_match(p, TOK_SEMI)) {
     52     if (named) return 1;
     53     type = kit_cg_type_record_decl(p->c, name, 0);
     54     if (type == KIT_CG_TYPE_NONE) {
     55       toy_error(p, p->cur.loc, "failed to declare record type");
     56       return 0;
     57     }
     58     return toy_add_named_type(p, name, type, TOY_NAMED_RECORD, type);
     59   }
     60   if (named) {
     61     if (named->kind != TOY_NAMED_RECORD) {
     62       toy_error(p, p->cur.loc, "record name already used for another type");
     63       return 0;
     64     }
     65     type = named->type;
     66     if (type == KIT_CG_TYPE_NONE) {
     67       type = kit_cg_type_record_decl(p->c, name, 0);
     68       if (type == KIT_CG_TYPE_NONE ||
     69           !toy_add_named_type(p, name, type, TOY_NAMED_RECORD, type)) {
     70         toy_error(p, p->cur.loc, "failed to declare record type");
     71         return 0;
     72       }
     73       named = toy_find_named_type(p, name);
     74     } else if (kit_cg_type_is_complete(p->c, type)) {
     75       toy_error(p, p->cur.loc, "record type redefinition");
     76       return 0;
     77     }
     78   } else {
     79     type = kit_cg_type_record_decl(p->c, name, 0);
     80     if (type == KIT_CG_TYPE_NONE ||
     81         !toy_add_named_type(p, name, type, TOY_NAMED_RECORD, type)) {
     82       toy_error(p, p->cur.loc, "failed to declare record type");
     83       return 0;
     84     }
     85     named = toy_find_named_type(p, name);
     86   }
     87   if (!toy_parser_expect(p, TOK_LBRACE)) {
     88     toy_error(p, p->cur.loc, "expected '{' after record name");
     89     return 0;
     90   }
     91   while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
     92     if (!toy_parser_reserve(p, (void**)&fields, &cap_fields, nfields + 1u,
     93                             sizeof *fields, "record fields") ||
     94         !toy_parser_reserve(p, (void**)&field_infos, &cap_field_infos,
     95                             nfields + 1u, sizeof *field_infos,
     96                             "record field info")) {
     97       goto done;
     98     }
     99     if (p->cur.kind != TOK_IDENT) {
    100       toy_error(p, p->cur.loc, "expected record field name");
    101       goto done;
    102     }
    103     fields[nfields].name = toy_tok_sym(p, p->cur);
    104     toy_parser_advance(p);
    105     if (!toy_parse_field_attr_list(p, &fields[nfields])) goto done;
    106     if (!toy_parser_expect(p, TOK_COLON)) {
    107       toy_error(p, p->cur.loc, "expected ':' after record field name");
    108       goto done;
    109     }
    110     fields[nfields].type = toy_parse_type(p);
    111     if (fields[nfields].type == KIT_CG_TYPE_NONE) goto done;
    112     field_infos[nfields].name = fields[nfields].name;
    113     field_infos[nfields].storage_type = fields[nfields].type;
    114     field_infos[nfields].toy_type = p->last_type;
    115     nfields++;
    116     if (!toy_parser_match(p, TOK_COMMA)) break;
    117   }
    118   if (!toy_parser_expect(p, TOK_RBRACE)) {
    119     toy_error(p, p->cur.loc, "expected '}' after record declaration");
    120     goto done;
    121   }
    122   if (packed) {
    123     size_t i;
    124     for (i = 0; i < nfields; ++i) {
    125       if (!fields[i].align_override) fields[i].align_override = 1;
    126     }
    127   }
    128   if (!toy_cg_record_complete(p, type, name, fields, (uint32_t)nfields, 0,
    129                               record_align)) {
    130     toy_error(p, p->cur.loc, "failed to create record type");
    131     goto done;
    132   }
    133   ok = named && toy_set_named_type_fields(p, named, field_infos, nfields);
    134 
    135 done:
    136   toy_parser_free_mem(p, fields, cap_fields * sizeof *fields);
    137   toy_parser_free_mem(p, field_infos, cap_field_infos * sizeof *field_infos);
    138   return ok;
    139 }
    140 
    141 int toy_parse_tuple_decl(ToyParser* p) {
    142   KitSym name;
    143   KitCgFieldDesc* fields = NULL;
    144   ToyRecordFieldInfo* field_infos = NULL;
    145   size_t nfields = 0;
    146   size_t cap_fields = 0;
    147   size_t cap_field_infos = 0;
    148   KitCgTypeId type;
    149   ToyNamedType* named;
    150   char field_name_buf[16];
    151   int ok = 0;
    152 
    153   if (!toy_parser_match(p, TOK_TUPLE)) return 0;
    154   if (!toy_skip_attr_list(p)) return 0;
    155   if (p->cur.kind != TOK_IDENT) {
    156     toy_error(p, p->cur.loc, "expected tuple name");
    157     return 0;
    158   }
    159   name = toy_tok_sym(p, p->cur);
    160   toy_parser_advance(p);
    161   if (!toy_parser_expect(p, TOK_LBRACE)) {
    162     toy_error(p, p->cur.loc, "expected '{' after tuple name");
    163     return 0;
    164   }
    165   while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    166     if (!toy_parser_reserve(p, (void**)&fields, &cap_fields, nfields + 1u,
    167                             sizeof *fields, "tuple fields") ||
    168         !toy_parser_reserve(p, (void**)&field_infos, &cap_field_infos,
    169                             nfields + 1u, sizeof *field_infos,
    170                             "tuple field info")) {
    171       goto done;
    172     }
    173     snprintf(field_name_buf, sizeof field_name_buf, "%u", (uint32_t)nfields);
    174     fields[nfields].name = kit_sym_intern(p->c, kit_slice_cstr(field_name_buf));
    175     fields[nfields].type = toy_parse_type(p);
    176     if (fields[nfields].type == KIT_CG_TYPE_NONE) goto done;
    177     field_infos[nfields].name = fields[nfields].name;
    178     field_infos[nfields].storage_type = fields[nfields].type;
    179     field_infos[nfields].toy_type = p->last_type;
    180     nfields++;
    181     if (!toy_parser_match(p, TOK_COMMA)) break;
    182   }
    183   if (!toy_parser_expect(p, TOK_RBRACE)) {
    184     toy_error(p, p->cur.loc, "expected '}' after tuple declaration");
    185     goto done;
    186   }
    187   type = toy_cg_record_type(p, name, fields, (uint32_t)nfields, 0, 0);
    188   if (type == KIT_CG_TYPE_NONE) {
    189     toy_error(p, p->cur.loc, "failed to create tuple type");
    190     goto done;
    191   }
    192   if (!toy_add_named_type(p, name, type, TOY_NAMED_TUPLE, type)) goto done;
    193   named = toy_find_named_type(p, name);
    194   ok = named && toy_set_named_type_fields(p, named, field_infos, nfields);
    195 
    196 done:
    197   toy_parser_free_mem(p, fields, cap_fields * sizeof *fields);
    198   toy_parser_free_mem(p, field_infos, cap_field_infos * sizeof *field_infos);
    199   return ok;
    200 }
    201 
    202 int toy_parse_enum_decl(ToyParser* p) {
    203   KitSym name;
    204   KitCgTypeId base;
    205   KitCgEnumValue* values = NULL;
    206   ToyEnumConst* toy_values = NULL;
    207   size_t nvalues = 0;
    208   size_t cap_values = 0;
    209   size_t cap_toy_values = 0;
    210   KitCgTypeId type;
    211   ToyNamedType* named;
    212   int ok = 0;
    213 
    214   if (!toy_parser_match(p, TOK_ENUM)) return 0;
    215   if (!toy_skip_attr_list(p)) return 0;
    216   if (p->cur.kind != TOK_IDENT) {
    217     toy_error(p, p->cur.loc, "expected enum name");
    218     return 0;
    219   }
    220   name = toy_tok_sym(p, p->cur);
    221   toy_parser_advance(p);
    222   if (!toy_parser_expect(p, TOK_COLON)) {
    223     toy_error(p, p->cur.loc, "expected enum base type");
    224     return 0;
    225   }
    226   base = toy_parse_type(p);
    227   if (base == KIT_CG_TYPE_NONE) return 0;
    228   if (!toy_parser_expect(p, TOK_LBRACE)) {
    229     toy_error(p, p->cur.loc, "expected '{' after enum base type");
    230     return 0;
    231   }
    232   while (p->cur.kind != TOK_RBRACE && p->cur.kind != TOK_EOF) {
    233     if (!toy_parser_reserve(p, (void**)&values, &cap_values, nvalues + 1u,
    234                             sizeof *values, "enum values") ||
    235         !toy_parser_reserve(p, (void**)&toy_values, &cap_toy_values,
    236                             nvalues + 1u, sizeof *toy_values,
    237                             "toy enum values")) {
    238       goto done;
    239     }
    240     if (!toy_parser_expect(p, TOK_DOT) || p->cur.kind != TOK_IDENT) {
    241       toy_error(p, p->cur.loc, "expected enum value");
    242       goto done;
    243     }
    244     values[nvalues].name = toy_tok_sym(p, p->cur);
    245     toy_values[nvalues].name = values[nvalues].name;
    246     toy_parser_advance(p);
    247     if (!toy_parser_expect(p, TOK_EQ) || p->cur.kind != TOK_NUMBER ||
    248         p->cur.is_float) {
    249       toy_error(p, p->cur.loc, "expected enum integer value");
    250       goto done;
    251     }
    252     values[nvalues].value = p->cur.int_value;
    253     toy_values[nvalues].value = p->cur.int_value;
    254     toy_parser_advance(p);
    255     nvalues++;
    256     if (!toy_parser_match(p, TOK_COMMA)) break;
    257   }
    258   if (!toy_parser_expect(p, TOK_RBRACE)) {
    259     toy_error(p, p->cur.loc, "expected '}' after enum declaration");
    260     goto done;
    261   }
    262   type = kit_cg_type_enum(p->c, name, base, values, (uint32_t)nvalues);
    263   if (type == KIT_CG_TYPE_NONE) {
    264     toy_error(p, p->cur.loc, "failed to create enum type");
    265     goto done;
    266   }
    267   if (!toy_add_named_type(p, name, type, TOY_NAMED_ENUM, base)) goto done;
    268   named = toy_find_named_type(p, name);
    269   ok = named && toy_set_named_type_enum_values(p, named, toy_values, nvalues);
    270 
    271 done:
    272   toy_parser_free_mem(p, values, cap_values * sizeof *values);
    273   toy_parser_free_mem(p, toy_values, cap_toy_values * sizeof *toy_values);
    274   return ok;
    275 }
    276 
    277 int toy_parse_alias_decl(ToyParser* p, int is_pub) {
    278   KitSym name;
    279   KitSym target_name;
    280   KitCgSym target_sym;
    281   KitCgAlias alias;
    282   ToyAttrSet attrs;
    283   KitSymBind default_bind = is_pub ? KIT_SB_GLOBAL : KIT_SB_LOCAL;
    284   if (!toy_parser_match(p, TOK_ALIAS)) return 0;
    285   if (!toy_parse_attr_list(p, &attrs, default_bind)) return 0;
    286   if (!toy_validate_attr_placement(p, &attrs, TOY_ATTR_SYMBOL,
    287                                    "invalid alias attribute"))
    288     return 0;
    289   if (p->cur.kind != TOK_IDENT) {
    290     toy_error(p, p->cur.loc, "expected alias name");
    291     return 0;
    292   }
    293   name = toy_tok_sym(p, p->cur);
    294   toy_parser_advance(p);
    295   if (!toy_parser_expect(p, TOK_EQ) || p->cur.kind != TOK_IDENT) {
    296     toy_error(p, p->cur.loc, "expected alias target");
    297     return 0;
    298   }
    299   target_name = toy_tok_sym(p, p->cur);
    300   toy_parser_advance(p);
    301   target_sym = toy_find_decl_sym(p, target_name);
    302   if (target_sym == KIT_CG_SYM_NONE) {
    303     toy_error(p, p->cur.loc, "undefined alias target");
    304     return 0;
    305   }
    306   memset(&alias, 0, sizeof alias);
    307   alias.linkage_name = toy_c_linkage_name(p, name);
    308   if (!alias.linkage_name) return 0;
    309   alias.display_name = name;
    310   alias.target = target_sym;
    311   alias.sym = attrs.sym;
    312   if (kit_cg_alias(p->cg, alias) == KIT_CG_SYM_NONE) {
    313     toy_error(p, p->cur.loc, "failed to define alias");
    314     return 0;
    315   }
    316   if (!toy_parser_expect(p, TOK_SEMI)) {
    317     toy_error(p, p->cur.loc, "expected ';' after alias");
    318     return 0;
    319   }
    320   return 1;
    321 }
    322 
    323 int toy_parse_fn(ToyParser* p, int is_extern, int is_pub) {
    324   KitSym name;
    325   KitCgTypeId ret_type;
    326   KitCgTypeId* param_types = NULL;
    327   ToyTypeId* param_toy_types = NULL;
    328   KitCgAbiAttrs* param_attrs = NULL;
    329   KitCgAbiAttrs ret_attrs;
    330   KitCgFuncParam* sig_params = NULL;
    331   KitSym* param_names = NULL;
    332   size_t nparams = 0;
    333   size_t cap_param_types = 0;
    334   size_t cap_param_toy_types = 0;
    335   size_t cap_param_attrs = 0;
    336   size_t cap_sig_params = 0;
    337   size_t cap_param_names = 0;
    338   int variadic = 0;
    339   KitCgDecl decl;
    340   KitCgFuncSig sig;
    341   KitCgTypeId fn_ty;
    342   ToyFn* fn_entry;
    343   ToyAttrSet attrs;
    344   ToyTypeId fn_toy_type;
    345   ToyTypeId ret_toy_type;
    346   size_t i;
    347   KitSymBind default_bind =
    348       (is_extern || is_pub ||
    349        p->input_kind != KIT_FRONTEND_INPUT_TRANSLATION_UNIT)
    350           ? KIT_SB_GLOBAL
    351           : KIT_SB_LOCAL;
    352 
    353   if (!toy_parser_match(p, TOK_FN)) return 0;
    354   if (!toy_parse_attr_list(p, &attrs, default_bind)) return -1;
    355   if (!toy_validate_attr_placement(
    356           p, &attrs, TOY_ATTR_SYMBOL | TOY_ATTR_FUNC | TOY_ATTR_SECTION,
    357           "invalid function attribute"))
    358     return -1;
    359   memset(&ret_attrs, 0, sizeof ret_attrs);
    360 
    361   if (p->cur.kind != TOK_IDENT) {
    362     toy_error(p, p->cur.loc, "expected function name");
    363     return -1;
    364   }
    365   name = toy_tok_sym(p, p->cur);
    366   toy_parser_advance(p);
    367 
    368   if (!toy_parser_expect(p, TOK_LPAREN)) {
    369     toy_error(p, p->cur.loc, "expected '(' after function name");
    370     return -1;
    371   }
    372 
    373   if (p->cur.kind != TOK_RPAREN) {
    374     for (;;) {
    375       if (p->cur.kind == TOK_DOTDOTDOT) {
    376         variadic = 1;
    377         toy_parser_advance(p);
    378         break;
    379       }
    380       if (p->cur.kind != TOK_IDENT) {
    381         toy_error(p, p->cur.loc, "expected parameter name");
    382         return -1;
    383       }
    384       if (!toy_parser_reserve(p, (void**)&param_types, &cap_param_types,
    385                               nparams + 1u, sizeof *param_types,
    386                               "function parameter types") ||
    387           !toy_parser_reserve(p, (void**)&param_attrs, &cap_param_attrs,
    388                               nparams + 1u, sizeof *param_attrs,
    389                               "function parameter attrs") ||
    390           !toy_parser_reserve(p, (void**)&param_toy_types, &cap_param_toy_types,
    391                               nparams + 1u, sizeof *param_toy_types,
    392                               "function parameter source types") ||
    393           !toy_parser_reserve(p, (void**)&sig_params, &cap_sig_params,
    394                               nparams + 1u, sizeof *sig_params,
    395                               "function signature parameters") ||
    396           !toy_parser_reserve(p, (void**)&param_names, &cap_param_names,
    397                               nparams + 1u, sizeof *param_names,
    398                               "function parameter names")) {
    399         return -1;
    400       }
    401       param_names[nparams] = toy_tok_sym(p, p->cur);
    402       toy_parser_advance(p);
    403       if (!toy_parse_abi_attr_list(p, &param_attrs[nparams])) return -1;
    404       if (!toy_parser_expect(p, TOK_COLON)) {
    405         toy_error(p, p->cur.loc, "expected ':' after parameter name");
    406         return -1;
    407       }
    408       param_types[nparams] = toy_parse_type(p);
    409       if (param_types[nparams] == KIT_CG_TYPE_NONE) return -1;
    410       param_toy_types[nparams] = p->last_type;
    411       nparams++;
    412       if (p->cur.kind == TOK_COMMA) {
    413         toy_parser_advance(p);
    414         if (p->cur.kind == TOK_DOTDOTDOT) {
    415           variadic = 1;
    416           toy_parser_advance(p);
    417           break;
    418         }
    419       } else {
    420         break;
    421       }
    422     }
    423   }
    424   if (!toy_parser_expect(p, TOK_RPAREN)) {
    425     toy_error(p, p->cur.loc, "expected ')' after parameters");
    426     return -1;
    427   }
    428 
    429   if (toy_parser_match(p, TOK_COLON)) {
    430     ret_type = toy_parse_type(p);
    431     if (ret_type == KIT_CG_TYPE_NONE) return -1;
    432     ret_toy_type = p->last_type;
    433     if (!toy_parse_abi_attr_list(p, &ret_attrs)) return -1;
    434   } else {
    435     ret_type = toy_builtin_type(p, KIT_CG_BUILTIN_VOID);
    436     ret_toy_type = toy_type_from_cg(p, ret_type);
    437   }
    438 
    439   for (i = 0; i < nparams; i++) {
    440     sig_params[i].type = param_types[i];
    441     sig_params[i].attrs = param_attrs[i];
    442   }
    443   memset(&sig, 0, sizeof sig);
    444   sig.result.type = ret_type;
    445   sig.result.attrs = ret_attrs;
    446   sig.params = sig_params;
    447   sig.nparams = (uint32_t)nparams;
    448   sig.call_conv = attrs.has_call_conv ? attrs.call_conv : KIT_CG_CC_TARGET_C;
    449   sig.abi_variadic = variadic;
    450 
    451   fn_ty = kit_cg_type_func(p->c, sig);
    452   if (fn_ty == KIT_CG_TYPE_NONE) {
    453     toy_error(p, p->cur.loc, "failed to create function type");
    454     return -1;
    455   }
    456   fn_toy_type = toy_type_register_func(p, fn_ty, ret_toy_type, param_toy_types,
    457                                        nparams, variadic);
    458 
    459   memset(&decl, 0, sizeof(decl));
    460   decl.kind = KIT_CG_DECL_FUNC;
    461   decl.linkage_name = toy_c_linkage_name(p, name);
    462   if (!decl.linkage_name) return -1;
    463   decl.display_name = name;
    464   decl.type = fn_ty;
    465   decl.sym = attrs.sym;
    466   if (toy_sym_is(p, name, "main")) decl.sym.bind = KIT_SB_GLOBAL;
    467   decl.as.func = attrs.func;
    468 
    469   {
    470     KitCgSym sym = kit_cg_decl(p->cg, decl);
    471     if (sym == KIT_CG_SYM_NONE) {
    472       toy_error(p, p->cur.loc, "failed to declare function");
    473       return -1;
    474     }
    475     fn_entry = toy_add_fn_typed(p, name, sym, fn_ty, fn_toy_type, ret_type,
    476                                 ret_toy_type, param_types, param_toy_types,
    477                                 nparams, variadic);
    478   }
    479   if (!fn_entry) {
    480     toy_error(p, p->cur.loc, "failed to declare function");
    481     return -1;
    482   }
    483   fn_entry->sym_attrs = decl.sym;
    484   fn_entry->func_attrs = decl.as.func;
    485 
    486   if (is_extern) {
    487     if (!toy_parser_expect(p, TOK_SEMI)) {
    488       toy_error(p, p->cur.loc, "expected ';' after extern function");
    489       return -1;
    490     }
    491     toy_parser_free_mem(p, param_types, cap_param_types * sizeof *param_types);
    492     toy_parser_free_mem(p, param_toy_types,
    493                         cap_param_toy_types * sizeof *param_toy_types);
    494     toy_parser_free_mem(p, param_attrs, cap_param_attrs * sizeof *param_attrs);
    495     toy_parser_free_mem(p, sig_params, cap_sig_params * sizeof *sig_params);
    496     toy_parser_free_mem(p, param_names, cap_param_names * sizeof *param_names);
    497     return 1;
    498   }
    499 
    500   kit_cg_func_begin_attrs(p->cg, toy_fn_cur_sym(p, fn_entry),
    501                           fn_entry->func_attrs);
    502 
    503   p->nvars = 0;
    504   p->nlabels = 0;
    505   p->cur_fn_ret = ret_type;
    506   p->cur_fn_ret_toy = ret_toy_type;
    507   for (i = 0; i < nparams; i++) {
    508     KitCgLocal param = kit_cg_param(p->cg, (uint32_t)i, param_types[i],
    509                                     toy_slot_attrs(param_names[i]));
    510     if (!toy_add_local_typed(p, param_names[i], param_types[i],
    511                              param_toy_types[i], param, 1))
    512       return -1;
    513   }
    514 
    515   if (!toy_parse_block(p)) return -1;
    516 
    517   if (ret_type == toy_builtin_type(p, KIT_CG_BUILTIN_VOID)) {
    518     kit_cg_ret(p->cg);
    519   }
    520 
    521   kit_cg_func_end(p->cg);
    522   p->nvars = 0;
    523   p->nlabels = 0;
    524   p->cur_fn_ret = toy_builtin_type(p, KIT_CG_BUILTIN_VOID);
    525   p->cur_fn_ret_toy = toy_type_from_cg(p, p->cur_fn_ret);
    526   toy_parser_free_mem(p, param_types, cap_param_types * sizeof *param_types);
    527   toy_parser_free_mem(p, param_toy_types,
    528                       cap_param_toy_types * sizeof *param_toy_types);
    529   toy_parser_free_mem(p, param_attrs, cap_param_attrs * sizeof *param_attrs);
    530   toy_parser_free_mem(p, sig_params, cap_sig_params * sizeof *sig_params);
    531   toy_parser_free_mem(p, param_names, cap_param_names * sizeof *param_names);
    532   return 1;
    533 }