Ticket #1147: nci_pmc_fixup_minimal.patch

File nci_pmc_fixup_minimal.patch, 19.4 KB (added by plobsing, 5 years ago)
  • src/pmc/nci.pmc

     
    1818 
    1919*/ 
    2020 
     21#include "parrot/nci.h" 
     22 
    2123typedef INTVAL (*nci_sub_t)(PARROT_INTERP, PMC *); 
    22 typedef INTVAL (*nci_jit_sub_t)(PARROT_INTERP, PMC *, char *); 
     24typedef nci_sub_t nci_jit_sub_t; 
    2325 
    24 void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info, 
    25                 size_t sig_length); 
    26 void pcc_params(PARROT_INTERP, STRING *sig, Parrot_NCI_attributes * const nci_info, 
    27                 size_t sig_length) { 
    28     char    param_buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 
    29     char   *param_sig    = sig_length <= 7 
    30                          ? param_buf 
    31                          : mem_allocate_n_typed(sig_length, char); 
    32     size_t  j            = 0; 
    33     size_t  i; 
     26#define NCI_raw_FLAG    PObj_private0_FLAG 
    3427 
    35     for (i = 1; i < sig_length; i++) { 
     28STRING *pcc_sig_params(PARROT_INTERP, STRING *sig); 
     29STRING *pcc_sig_params(PARROT_INTERP, STRING *sig) { 
     30    size_t sig_len = Parrot_str_byte_length(interp, sig); 
     31    char param_buf[sig_len*2]; 
     32 
     33    size_t i, j; 
     34 
     35    for (i = 1, j = 0; i < sig_len; i++) { 
    3636        INTVAL c = Parrot_str_indexed(interp, sig, i); 
    37  
    38         switch (c) { 
    39             case (INTVAL)'0':    /* null ptr or such - doesn't consume a reg */ 
    40                 break; 
    41             case (INTVAL)'f': 
    42             case (INTVAL)'N': 
    43             case (INTVAL)'d': 
    44                 param_sig[j++] = 'N'; 
    45                 break; 
    46             case (INTVAL)'I':   /* INTVAL */ 
    47             case (INTVAL)'l':   /* long */ 
    48             case (INTVAL)'i':   /* int */ 
    49             case (INTVAL)'s':   /* short */ 
    50             case (INTVAL)'c':   /* char */ 
    51                 param_sig[j++] = 'I'; 
    52                 break; 
    53             case (INTVAL)'S': 
    54             case (INTVAL)'t':   /* string, pass a cstring */ 
    55                 param_sig[j++] = 'S'; 
    56                 break; 
    57             case (INTVAL)'J':   /* interpreter */ 
    58                 break; 
    59             case (INTVAL)'p':   /* push pmc->data */ 
    60             case (INTVAL)'O':   /* push PMC * object in P2 */ 
    61             case (INTVAL)'P':   /* push PMC * */ 
    62             case (INTVAL)'V':   /* push PMC * */ 
    63                 param_sig[j++] = 'P'; 
    64             case (INTVAL)'v': 
    65                 break; 
    66                 /* I have no idea how to handle these */ 
    67             case (INTVAL)'2': 
    68             case (INTVAL)'3': 
    69             case (INTVAL)'4': 
    70                 param_sig[j++] = 'I'; 
    71                 break; 
    72             case (INTVAL)'@': 
    73                 param_sig[j++] = '@'; 
    74                 break; 
    75             case (INTVAL)'b': /* buffer (void*) pass Buffer_bufstart(SReg) */ 
    76             case (INTVAL)'B': /* buffer (void**) pass &Buffer_bufstart(SReg) */ 
    77                 param_sig[j++] = 'S'; 
    78                 break; 
    79             default: 
    80                 if (sig_length > 7) 
    81                     mem_sys_free(param_sig); 
    82                 Parrot_ex_throw_from_c_args(interp, NULL, 
     37        if (c > 127) { 
     38            Parrot_ex_throw_from_c_args(interp, NULL, 
    8339                    EXCEPTION_JIT_ERROR, 
    84                     "Unknown param Signature %c\n", (char)c); 
    85                 break; 
     40                    "Unknown param type at %d in signature '%S' (way too big)\n", i, sig); 
    8641        } 
     42        else { 
     43            switch ((char)c) { 
     44                case 'v': 
     45                case '0': 
     46                case 'J': 
     47                    break; 
     48                case 'N': 
     49                case 'd': 
     50                case 'f': 
     51                    param_buf[j++] = 'N'; 
     52                    break; 
     53                case 'I': 
     54                case 'l': 
     55                case 'i': 
     56                case 's': 
     57                case 'c': 
     58                    param_buf[j++] = 'I'; 
     59                    break; 
     60                case 'S': 
     61                case 't': 
     62                case 'b': 
     63                case 'B': 
     64                    param_buf[j++] = 'S'; 
     65                    break; 
     66                case 'P': 
     67                case 'p': 
     68                case 'V': 
     69                case '2': 
     70                case '3': 
     71                case '4': 
     72                    param_buf[j++] = 'P'; 
     73                    break; 
     74                case 'O': 
     75                    param_buf[j++] = 'P'; 
     76                    param_buf[j++] = 'i'; 
     77                    break; 
     78                case '@': 
     79                    param_buf[j++] = 'P'; 
     80                    param_buf[j++] = 's'; 
     81                    break; 
     82                default: 
     83                    Parrot_ex_throw_from_c_args(interp, NULL, 
     84                            EXCEPTION_JIT_ERROR, 
     85                            "Unknown param type at %d in signature '%S'\n", i, sig); 
     86            } 
     87        } 
    8788    } 
    8889 
    89     PARROT_ASSERT(j <= sig_length); 
     90    return string_make(interp, param_buf, j, NULL, PObj_constant_FLAG); 
     91} 
    9092 
    91     /* use only the signature-significant part of the string buffer */ 
    92     if (j) { 
    93         nci_info->pcc_params_signature = string_make(interp, param_sig, j, 
    94             NULL, PObj_constant_FLAG); 
     93STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig); 
     94STRING *pcc_sig_ret(PARROT_INTERP, STRING *sig) { 
     95    INTVAL c = Parrot_str_indexed(interp, sig, 0); 
     96    if (c > 127) { 
     97        Parrot_ex_throw_from_c_args(interp, NULL, 
     98                EXCEPTION_JIT_ERROR, 
     99                "Unknown return type at %d in signature '%S' (way too big)\n", 0, sig); 
    95100    } 
    96     else 
    97         nci_info->pcc_params_signature = CONST_STRING(interp, ""); 
    98  
    99     if (sig_length > 7) 
    100         mem_sys_free(param_sig); 
     101    else { 
     102        switch ((char)c) { 
     103            case 'v': 
     104                return CONST_STRING(interp, "v"); 
     105            case 'N': 
     106            case 'f': 
     107            case 'd': 
     108                return CONST_STRING(interp, "N"); 
     109            case 'I': 
     110            case 'l': 
     111            case 'i': 
     112            case 's': 
     113            case 'c': 
     114                return CONST_STRING(interp, "I"); 
     115            case 'S': 
     116            case 't': 
     117                return CONST_STRING(interp, "S"); 
     118            case 'p': 
     119            case 'P': 
     120                return CONST_STRING(interp, "P"); 
     121            case '2': 
     122            case '3': 
     123            case '4': 
     124                return CONST_STRING(interp, "P"); 
     125            default: 
     126                Parrot_ex_throw_from_c_args(interp, NULL, 
     127                        EXCEPTION_JIT_ERROR, 
     128                        "Unknown return type at %d in signature '%S'\n", 0, sig); 
     129        } 
     130    } 
    101131} 
    102132 
    103133/* actually build the NCI thunk */ 
     
    106136static 
    107137nci_sub_t build_func(PARROT_INTERP, PMC *pmc, Parrot_NCI_attributes *nci_info) 
    108138{ 
    109     STRING    *key        = nci_info->signature; 
    110     size_t     key_length = Parrot_str_byte_length(interp, key); 
     139    STRING    *key        = nci_info->nci_signature; 
    111140    int       jitted      = 0; 
    112141 
    113     pcc_params(interp, key, nci_info, key_length); 
    114  
    115     /* Arity is length of that string minus one (the return type). */ 
    116     nci_info->arity       = key_length - 1; 
    117  
    118142    /* Build call function. */ 
    119143    nci_info->func        = (PMC *)(build_call_func(interp, pmc, key, &jitted)); 
    120     nci_info->jitted      = jitted; 
    121144 
    122145    return (nci_sub_t)nci_info->func; 
    123146} 
    124147 
    125148 
    126149pmclass NCI auto_attrs { 
    127     ATTR STRING    *signature;              /* The signature. */ 
    128     ATTR void      *func;                   /* Function pointer to call. */ 
    129     ATTR void      *orig_func;              /* Function pointer 
    130                                              * used to create func */ 
    131     ATTR STRING    *pcc_params_signature;   /* The signature. */ 
    132     ATTR STRING    *long_signature;         /* The full signature. */ 
    133     ATTR PMC       *multi_sig;              /* type tuple array (?) */ 
    134     ATTR INTVAL     arity;                  /* Cached arity of the NCI. */ 
    135     ATTR INTVAL     jitted;                 /* Is this a jitted NCI stub. */ 
     150    /* Signature Attributes */ 
     151    ATTR STRING    *nci_signature;          /* The NCI signature */ 
     152    ATTR STRING    *pcc_signature_ret;      /* The PCC return signature */ 
     153    ATTR STRING    *pcc_signature_param;    /* The PCC param signature */ 
    136154 
     155    /* Function Pointers */ 
     156    ATTR void      *func;                   /* Function pointer to call */ 
     157    ATTR void      *orig_func;              /* Function pointer being wrapped */ 
     158 
     159    /* Sub PMC Attributes */ 
     160    ATTR INTVAL     arity;                  /* Number of params taken */ 
     161    /* MMD Attributes */ 
     162    ATTR PMC       *multi_sig; 
     163    ATTR STRING    *long_signature; 
     164 
    137165/* 
    138166 
    139 =item C<METHOD get_multisig()> 
     167=item C<void init()> 
    140168 
    141 Return the MMD signature PMC, if any or a Null PMC. 
     169Initializes the NCI with a C<NULL> function pointer. 
    142170 
    143171=cut 
    144172 
    145173*/ 
    146174 
    147     METHOD get_multisig() { 
    148         PMC *sig; 
    149         GET_ATTR_multi_sig(INTERP, SELF, sig); 
    150         if (PMC_IS_NULL(sig)) 
    151             sig = PMCNULL; 
    152         RETURN(PMC *sig); 
     175    VTABLE void init() { 
     176        /* Mark that we're not a raw NCI */ 
     177        PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 
     178        /* Mark that we have a custom gc marker */ 
     179        PObj_custom_mark_SET(SELF); 
    153180    } 
    154181 
    155182/* 
    156183 
    157 =item C<METHOD set_raw_nci_ptr(void *func)> 
     184=item C<void *get_pointer()> 
    158185 
    159 Sets the specified function pointer and raw flag. 
     186=item C<void set_pointer(void *ptr)> 
    160187 
     188Get/Set the pointer being wrapped. Setting through this interface sets 
     189the raw flag. 
     190 
    161191=cut 
    162192 
    163193*/ 
    164194 
    165     METHOD make_raw_nci(PMC *func) { 
    166         VTABLE_set_pointer(interp, SELF, (void *)func); 
     195    VTABLE void *get_pointer() { 
     196        return PARROT_NCI(SELF)->orig_func; 
    167197    } 
    168198 
     199    VTABLE void set_pointer(void *ptr) { 
     200        SET_ATTR_orig_func(INTERP, SELF, ptr); 
     201        PObj_get_FLAGS(SELF) |= NCI_raw_FLAG; 
     202    } 
     203 
    169204/* 
    170205 
    171 =item C<void init()> 
     206=item C<STRING *get_string()> 
    172207 
    173 Initializes the NCI with a C<NULL> function pointer. 
     208=item C<void set_string(STRING *str)> 
    174209 
     210Get/Set the NCI signature. 
     211 
    175212=cut 
    176213 
    177214*/ 
    178215 
    179     VTABLE void init() { 
    180         /* Mark that we're not a raw NCI. */ 
    181         PObj_flag_CLEAR(private2, SELF); 
    182         PObj_custom_mark_SET(SELF); 
     216    VTABLE STRING *get_string() { 
     217        return PARROT_NCI(SELF)->nci_signature; 
    183218    } 
    184219 
     220    VTABLE void set_string_native(STRING *str) { 
     221        if (!PObj_constant_TEST(str)) { 
     222            str = Parrot_str_copy(INTERP, str); 
     223        } 
     224        SET_ATTR_nci_signature(INTERP, SELF, str); 
     225 
     226        /* set up derivative attributes */ 
     227        SET_ATTR_pcc_signature_param(INTERP, SELF, pcc_sig_params(INTERP, str)); 
     228        SET_ATTR_pcc_signature_ret(INTERP, SELF, pcc_sig_ret(INTERP, str)); 
     229        /* Arity is length of the NCI signature minus one (the return type). */ 
     230        SET_ATTR_arity(INTERP, SELF, Parrot_str_byte_length(INTERP, str) - 1); 
     231    } 
     232 
    185233/* 
    186234 
    187235=item C<void set_pointer_keyed_str(STRING *key, void *func)> 
    188236 
    189 Sets the specified function pointer and signature (C<*key>). 
     237Roughly equivalent to C<set_string(key)> and C<set_pointer(func)>. 
     238Setting through this interface clears the raw flag. 
    190239 
    191240=cut 
    192241 
    193242*/ 
    194243 
    195     VTABLE void set_pointer(void *ptr) { 
    196         SET_ATTR_orig_func(INTERP, SELF, ptr); 
    197         PObj_flag_SET(private2, SELF); 
    198     } 
    199  
    200     VTABLE void *get_pointer() { 
    201         return PARROT_NCI(SELF)->orig_func; 
    202     } 
    203  
    204244    VTABLE void set_pointer_keyed_str(STRING *key, void *func) { 
    205         Parrot_NCI_attributes * const nci_info   = PARROT_NCI(SELF); 
    206  
    207         /* Store the original function and signature. */ 
    208         SET_ATTR_orig_func(INTERP, SELF, func); 
    209  
    210         /* ensure that the STRING signature is constant */ 
    211         if (!PObj_constant_TEST(key)) { 
    212             char * const key_c      = Parrot_str_to_cstring(INTERP, key); 
    213             size_t       key_length = Parrot_str_byte_length(interp, key); 
    214             key                     = string_make(interp, key_c, key_length, 
    215                                         NULL, PObj_constant_FLAG); 
    216             Parrot_str_free_cstring(key_c); 
    217         } 
    218  
    219         nci_info->signature = key; 
     245        SELF.set_string_native(key); 
     246        SELF.set_pointer(func); 
     247        PObj_get_FLAGS(SELF) &= ~NCI_raw_FLAG; 
    220248    } 
    221249 
    222250/* 
     
    232260        if (PARROT_NCI(SELF)) { 
    233261            Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 
    234262 
    235             Parrot_gc_mark_STRING_alive(interp, nci_info->signature); 
    236             Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_params_signature); 
     263            Parrot_gc_mark_STRING_alive(interp, nci_info->nci_signature); 
     264            Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_param); 
     265            Parrot_gc_mark_STRING_alive(interp, nci_info->pcc_signature_ret); 
    237266            Parrot_gc_mark_STRING_alive(interp, nci_info->long_signature); 
    238267            Parrot_gc_mark_PMC_alive(interp, nci_info->multi_sig); 
    239268        } 
     
    262291         * ManagedStruct or Buffer? 
    263292         */ 
    264293        nci_info_ret->func                  = nci_info_self->func; 
    265         nci_info_ret->orig_func             = nci_info_self->orig_func; 
    266         nci_info_ret->signature             = nci_info_self->signature; 
    267         nci_info_ret->pcc_params_signature  = nci_info_self->pcc_params_signature; 
     294        nci_info_ret->orig_func              = nci_info_self->orig_func; 
     295        nci_info_ret->nci_signature         = nci_info_self->nci_signature; 
     296        nci_info_ret->pcc_signature_param   = nci_info_self->pcc_signature_param; 
     297        nci_info_ret->pcc_signature_ret     = nci_info_self->pcc_signature_ret; 
     298        nci_info_ret->long_signature        = nci_info_self->long_signature; 
     299        nci_info_ret->multi_sig             = nci_info_self->multi_sig; 
    268300        nci_info_ret->arity                 = nci_info_self->arity; 
    269         nci_info_ret->jitted                = nci_info_self->jitted; 
    270301        PObj_get_FLAGS(ret)                |= (PObj_get_FLAGS(SELF) & 0x7); 
    271302 
    272303        return ret; 
     
    306337        PMC                          *cont; 
    307338 
    308339        GET_ATTR_orig_func(INTERP, SELF, orig_func); 
    309         func = PObj_flag_TEST(private2, SELF) 
     340        func = PObj_get_FLAGS(SELF) & NCI_raw_FLAG 
    310341            ? (nci_sub_t) D2FPTR(orig_func) 
    311342            : (nci_sub_t) D2FPTR(nci_info->func); 
    312343 
     
    320351                    "attempt to call NULL function"); 
    321352        } 
    322353 
    323         if (nci_info->jitted) { 
    324             nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); 
     354        func(INTERP, SELF); 
    325355 
    326             /* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */ 
    327             sig_str = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature); 
    328             jit_func(INTERP, SELF, sig_str); 
    329             Parrot_str_free_cstring(sig_str); 
    330         } 
    331         else { 
    332             if (PObj_flag_TEST(private2, SELF)) { 
    333                 /* Parrot_eprintf(interp, "RAW NCI CALL\n"); */ 
    334             } 
    335             else { 
    336                 /* Parrot_eprintf(interp, "HACKED %S\n", nci_info->signature); */ 
    337             } 
    338             func(INTERP, SELF); 
    339         } 
    340356        cont = INTERP->current_cont; 
    341357 
    342358        /* 
     
    389405 
    390406/* 
    391407 
     408=item C<METHOD get_multisig()> 
     409 
     410Return the MMD signature PMC, if any or a Null PMC. 
     411 
     412=cut 
     413 
     414*/ 
     415 
     416    METHOD get_multisig() { 
     417        PMC *sig; 
     418        GET_ATTR_multi_sig(INTERP, SELF, sig); 
     419        if (sig == NULL) { 
     420            sig = PMCNULL; 
     421        } 
     422        RETURN(PMC *sig); 
     423    } 
     424 
     425/* 
     426 
    392427=item C<METHOD arity()> 
    393428 
    394429Return the arity of the NCI (the number of arguments). 
     
    397432 
    398433*/ 
    399434    METHOD arity() { 
    400         Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); 
    401         INTVAL arity = 0; 
     435        INTVAL arity; 
     436        GET_ATTR_arity(INTERP, SELF, arity); 
     437        RETURN(INTVAL arity); 
     438    } 
    402439 
    403         if (nci_info) { 
    404             if (!nci_info->func) 
    405                 build_func(INTERP, SELF, nci_info); 
    406             if (nci_info->func) { 
    407                 arity = nci_info->arity; 
    408                 RETURN(INTVAL arity); 
    409             } 
     440/* 
     441 
     442=item C<METHOD set_raw_nci_ptr(void *func)> 
     443 
     444Sets the specified function pointer and raw flag. 
     445 
     446=cut 
     447 
     448*/ 
     449 
     450    METHOD make_raw_nci(PMC *func) { 
     451        VTABLE_set_pointer(interp, SELF, (void *)func); 
     452    } 
     453 
     454/* 
     455 
     456=item C<INTVAL get_integer_keyed_int(INTVAL key)> 
     457 
     458=item C<STRING *get_string_keyed_int(INTVAL key)> 
     459 
     460=item C<PMC *get_pmc_keyed_int(INTVAL key)> 
     461 
     462Accessors for all attributes of this class not otherwise accessible through VTABLES. 
     463Integers are used for keys to make access easier for JIT. These are also available to 
     464PIR from F<runtime/parrot/include/nci.pasm> 
     465 
     466=over 
     467 
     468=item INTVAL keys 
     469 
     470C<PARROT_NCI_ARITY> 
     471 
     472=item STRING keys 
     473 
     474C<PARROT_NCI_PCC_SIGNATURE_PARAMS>, C<PARROT_NCI_PCC_SIGNATURE_RET>, 
     475C<PARROT_LONG_SIGNATURE> 
     476 
     477=item PMC keys 
     478 
     479C<PARROT_NCI_MULTI_SIG> 
     480 
     481=back 
     482 
     483=cut 
     484 
     485*/ 
     486 
     487    VTABLE INTVAL get_integer_keyed_int(INTVAL key) { 
     488        switch (key) { 
     489            case PARROT_NCI_ARITY: 
     490                return PARROT_NCI(SELF)->arity; 
     491            default: 
     492                Parrot_ex_throw_from_c_args(INTERP, NULL, 
     493                    EXCEPTION_INVALID_OPERATION, 
     494                    "Bad index for NCI.get_integer_keyed_int()"); 
    410495        } 
     496    } 
    411497 
    412         Parrot_ex_throw_from_c_args(INTERP, NULL, 
    413             EXCEPTION_INVALID_OPERATION, 
    414             "You cannot get the arity of an undefined NCI."); 
     498    VTABLE STRING *get_string_keyed_int(INTVAL key) { 
     499        switch (key) { 
     500            case PARROT_NCI_PCC_SIGNATURE_PARAMS: 
     501                return PARROT_NCI(SELF)->pcc_signature_param; 
     502            case PARROT_NCI_PCC_SIGNATURE_RET: 
     503                return PARROT_NCI(SELF)->pcc_signature_ret; 
     504            case PARROT_NCI_LONG_SIGNATURE: 
     505                return PARROT_NCI(SELF)->long_signature; 
     506            default: 
     507                Parrot_ex_throw_from_c_args(INTERP, NULL, 
     508                    EXCEPTION_INVALID_OPERATION, 
     509                    "Bad index for NCI.get_string_keyed_int()"); 
     510        } 
    415511    } 
     512 
     513    VTABLE PMC *get_pmc_keyed_int(INTVAL key) { 
     514        PMC *retval; 
     515        switch (key) { 
     516            case PARROT_NCI_MULTI_SIG: 
     517                GET_ATTR_multi_sig(INTERP, SELF, retval); 
     518            default: 
     519                Parrot_ex_throw_from_c_args(INTERP, NULL, 
     520                    EXCEPTION_INVALID_OPERATION, 
     521                    "Bad index for NCI.get_pmc_keyed_int()"); 
     522        } 
     523        if (retval == NULL) { 
     524            retval = PMCNULL; 
     525        } 
     526        return retval; 
     527    } 
    416528} 
    417529 
    418530/* 
  • include/parrot/nci.h

     
    1515 
    1616#include "parrot/parrot.h" 
    1717 
     18/* NCI PMC interface constants */ 
     19/* &gen_from_enum(nci.pasm) */ 
     20typedef enum { 
     21    PARROT_NCI_ARITY, 
     22    PARROT_NCI_PCC_SIGNATURE_PARAMS, 
     23    PARROT_NCI_PCC_SIGNATURE_RET, 
     24    PARROT_NCI_LONG_SIGNATURE, 
     25    PARROT_NCI_MULTI_SIG, 
     26} parrot_nci_enum_t; 
     27/* &end_gen */ 
     28 
    1829void *build_call_func(PARROT_INTERP, SHIM(PMC *pmc_nci), NOTNULL(STRING *signature), NOTNULL(int *jitted)); 
    1930 
    2031#endif /* PARROT_NCI_H_GUARD */ 
  • config/gen/parrot_include.pm

     
    3939        include/parrot/library.h 
    4040        include/parrot/longopt.h 
    4141        include/parrot/multidispatch.h 
     42        include/parrot/nci.h 
    4243        include/parrot/packfile.h 
    4344        include/parrot/stat.h 
    4445        include/parrot/string.h 
    4546        include/parrot/pmc.h 
    4647        include/parrot/warnings.h 
    4748        include/parrot/gc_api.h 
    48         src/pmc/timer.pmc 
    4949        src/utils.c 
    5050    ) ]; 
    5151    $data{generated_files} = [ qw(