Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // File: feature-gen.h
- #define GENERATE_ALL_FEATURES() \
- FEATURE_DEFINE ('b', FEATURE_BAREWORD_FILEHANDLES, "bareword_filehandles") \
- FEATURE_DEFINE ('b', FEATURE_BITWISE, "bitwise") \
- FEATURE_DEFINE ('e', FEATURE_EVALBYTES, "evalbytes") \
- FEATURE_DEFINE ('f', FEATURE_FC, "fc") \
- FEATURE_DEFINE ('i', FEATURE_INDIRECT, "indirect") \
- FEATURE_DEFINE ('i', FEATURE_ISA, "isa") \
- FEATURE_DEFINE ('m', FEATURE_MULTIDIMENSIONAL, "multidimensional") \
- FEATURE_DEFINE ('m', FEATURE_MYREF, "myref") \
- FEATURE_DEFINE ('p', FEATURE_POSTDEREF_QQ, "postderef_qq") \
- FEATURE_DEFINE ('r', FEATURE_REFALIASING, "refaliasing") \
- FEATURE_DEFINE ('s', FEATURE_SAY, "say") \
- FEATURE_DEFINE ('s', FEATURE_SIGNATURES, "signatures") \
- FEATURE_DEFINE ('s', FEATURE_STATE, "state") \
- FEATURE_DEFINE ('s', FEATURE_SWITCH, "switch") \
- FEATURE_DEFINE ('t', FEATURE_TRY, "try") \
- FEATURE_DEFINE ('u', FEATURE_UNICODE, "unicode") \
- FEATURE_DEFINE ('u', FEATURE_UNIEVAL, "unieval") \
- FEATURE_DEFINE ('_', FEATURE___SUB__, "__SUB__")
- #define GENERATE_ALL_FEATURE_BUNDLES() \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_DEFAULT, ( \
- BUNDLE_ENABLE (FEATURE_INDIRECT) \
- BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES) \
- )) \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_510, ( \
- BUNDLE_ENABLE (FEATURE_INDIRECT) \
- BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES) \
- BUNDLE_ENABLE (FEATURE_SAY) \
- BUNDLE_ENABLE (FEATURE_STATE) \
- BUNDLE_ENABLE (FEATURE_SWITCH) \
- )) \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_511, ( \
- BUNDLE_ENABLE (FEATURE_INDIRECT) \
- BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES) \
- BUNDLE_ENABLE (FEATURE_SAY) \
- BUNDLE_ENABLE (FEATURE_STATE) \
- BUNDLE_ENABLE (FEATURE_SWITCH) \
- BUNDLE_ENABLE (FEATURE_UNICODE) \
- )) \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_515, ( \
- BUNDLE_ENABLE (FEATURE_INDIRECT) \
- BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES) \
- BUNDLE_ENABLE (FEATURE_SAY) \
- BUNDLE_ENABLE (FEATURE_STATE) \
- BUNDLE_ENABLE (FEATURE_SWITCH) \
- BUNDLE_ENABLE (FEATURE_UNICODE) \
- BUNDLE_ENABLE (FEATURE_UNIEVAL) \
- BUNDLE_ENABLE (FEATURE_EVALBYTES) \
- BUNDLE_ENABLE (FEATURE___SUB__) \
- BUNDLE_ENABLE (FEATURE_FC) \
- )) \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_523, ( \
- BUNDLE_ENABLE (FEATURE_INDIRECT) \
- BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES) \
- BUNDLE_ENABLE (FEATURE_SAY) \
- BUNDLE_ENABLE (FEATURE_STATE) \
- BUNDLE_ENABLE (FEATURE_SWITCH) \
- BUNDLE_ENABLE (FEATURE_UNICODE) \
- BUNDLE_ENABLE (FEATURE_UNIEVAL) \
- BUNDLE_ENABLE (FEATURE_EVALBYTES) \
- BUNDLE_ENABLE (FEATURE___SUB__) \
- BUNDLE_ENABLE (FEATURE_FC) \
- BUNDLE_ENABLE (FEATURE_POSTDEREF_QQ) \
- )) \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_527, ( \
- BUNDLE_ENABLE (FEATURE_INDIRECT) \
- BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)\ \
- BUNDLE_ENABLE (FEATURE_SAY) \
- BUNDLE_ENABLE (FEATURE_STATE) \
- BUNDLE_ENABLE (FEATURE_SWITCH) \
- BUNDLE_ENABLE (FEATURE_UNICODE) \
- BUNDLE_ENABLE (FEATURE_UNIEVAL) \
- BUNDLE_ENABLE (FEATURE_EVALBYTES) \
- BUNDLE_ENABLE (FEATURE___SUB__) \
- BUNDLE_ENABLE (FEATURE_FC) \
- BUNDLE_ENABLE (FEATURE_POSTDEREF_QQ) \
- BUNDLE_ENABLE (FEATURE_BITWISE) \
- )) \
- BUNDLE_DEFINE ( FEATURE_BUNDLE_700, ( \
- BUNDLE_DEPRECATE (FEATURE_INDIRECT) \
- BUNDLE_PROHIBIT (FEATURE_MULTIDIMENSIONAL) \
- BUNDLE_PROHIBIT (FEATURE_BAREWORD_FILEHANDLES) \
- BUNDLE_ENABLE (FEATURE_SAY) \
- BUNDLE_ENABLE (FEATURE_STATE) \
- BUNDLE_ENABLE (FEATURE_SWITCH) \
- BUNDLE_ENABLE (FEATURE_UNICODE) \
- BUNDLE_ENABLE (FEATURE_UNIEVAL) \
- BUNDLE_ENABLE (FEATURE_EVALBYTES) \
- BUNDLE_ENABLE (FEATURE___SUB__) \
- BUNDLE_ENABLE (FEATURE_FC) \
- BUNDLE_ENABLE (FEATURE_POSTDEREF_QQ) \
- BUNDLE_ENABLE (FEATURE_BITWISE) \
- ))
- // End of file: feature-gen.h
- // File: feature.h
- typedef enum feature_t {
- FEATURE_NOT_FOUND = -1,
- #define FEATURE_DEFINE(Bucket, Symbol, Name) Symbol,
- GENERATE_ALL_FEATURES()
- #undef FEATURE_DEFINE
- NUMBER_OF_FEATURES
- } feature_t;
- typedef struct feature_name_t {
- STRLEN length;
- const char *name;
- } feature_name_t;
- typedef U32 features_bits_t[ 1 + ((NUMBER_OF_FEATURES - 1) >> 5) ];
- typedef struct features_t {
- // current
- features_bits_t state;
- // protocol enhancement
- features_bits_t is_set;
- features_bits_t protocol;
- features_bits_t change_deprecated;
- features_bits_t change_prohibited;
- } features_t;
- typedef struct feature_protocol_t {
- features_bits_t state;
- features_bits_t change_deprecated;
- features_bits_t change_prohibited;
- } feature_protocol_t;
- #define BUNDLE_DEFINE(Name, Content) \
- extern const feature_protocol_t const * FEATURE_BUNDLE_ ## Name;
- GENERATE_ALL_FEATURE_BUNDLES()
- #undef BUNDLE_DEFINE
- bool feature_is_enabled (features_t *set, feature_t feature);
- void feature_set_value (features_t *set, feature_t feature, bool value);
- void feature_set_bundle (features_t *set, feature_protocol_t *bundle);
- feature_t find_feature_by_name (const char *keypv, STRLEN keylen);
- // modified existing generated code
- #define magic_sethint_feature(keysv, keypv, keylen, valsv, valbool) \
- S_magic_sethint_feature(aTHX_ (keysv), (keypv), (keylen), (valsv), (valbool))
- PERL_STATIC_INLINE void
- S_magic_sethint_feature(pTHX_ SV *keysv, const char *keypv, STRLEN keylen,
- SV *valsv, bool valbool) {
- if (keysv)
- keypv = SvPV_const(keysv, keylen);
- feature_t feature = find_feature_by_name (keypv, keylen);
- if (feature > FEATURE_NOT_FOUND)
- feature_set (PL_compiling.cop_features, feature, valsv ? SvTRUE(valsv) : valbool);
- }
- // End of file: feature.h
- // File: feature.c
- static feature_name_t feature_names[] = {
- # define FEATURE_DEFINE(Bucket, Symbol, Name) \
- [Symbol] = ( (feature_name_t) { .length = sizeof (Name) - 1, .name = Name } ),
- GENERATE_ALL_FEATURES()
- # undef FEATURE_DEFINE
- };
- static feature_t feature_name_lookup[] = {
- # define FEATURE_DEFINE(Bucket, Symbol, Name) [Bucket] = Symbol,
- GENERATE_ALL_FEATURES()
- # undef FEATURE_DEFINE
- };
- #define FEATURE_OFFSET(Feature) \
- ((Feature) >> 5)
- #define FEATURE_MASK(Feature) \
- (1 << ((Feature) & 0x1f))
- #define SIZEOF_ARRAY(Array) \
- (sizeof (Array) / sizeof ( ((Array) {})[0]))
- bool feature_is_enabled (features_t *set, feature_t feature) {
- U32 mask = FEATURE_MASK (feature);
- U32 offset = FEATURE_OFFSET (feature);
- return set->is_set[offset] & mask ? 1 : 0;
- }
- void feature_set_value (features_t *set, feature_t feature, bool value) {
- U32 mask = FEATURE_MASK (feature);
- U32 offset = FEATURE_OFFSET (feature);
- U32 new_value = value ? mask : 0;
- if (set->protocol[offset] & mask != new_value) {
- if (set->change_prohibited[offset] & mask) {
- // die
- return;
- }
- if (set->change_deprecated[offset] & mask) {
- // warn
- }
- }
- set->is_set[offset] |= mask;
- if (value)
- set->state[offset] |= mask;
- else
- set->state[offset] &= ~mask;
- }
- void feature_set_bundle (features_t *set, feature_protocol_t *bundle) {
- // bundle just copies its definition over current
- bzero (set->is_set, sizeof (set->is_set));
- memcpy (set->bundle, bundle->state, sizeof (bundle->state));
- }
- void feature_set_protocol (features_t *set, feature_protocol_t *protocol) {
- // protocol merges deprecated and prohibited with current
- // and modifies only those explicitly mentioned
- // ie:
- // use feature 'fc';
- // use v5.10;
- // ... fc still available
- for (U32 i = 0; i < SIZEOF_ARRAY (feature_bits_t); ++i) {
- U32 mask = set->change_prohibited[i] & protocol->is_set[i];
- if (mask && ((set->protocol[i] & mask) ^ (protocol->state & mask))) {
- // current protocol prohibits some bits that new protocol is about to change
- // do not set any feature before checking all
- report error and return;
- }
- }
- for (U32 i = 0; i < SIZEOF_ARRAY (feature_bits_t); ++i) {
- U32 mask = set->change_deprecated[i] & protocol->is_set[i];
- if (mask && ((set->protocol[i] & mask) ^ (protocol->state & mask))) {
- // current protocol prohibits some bits that new protocol is about to change
- warn;
- }
- // clear is_set bits - bundle overrides them
- set->is_set[i] &= ~ protocol->is_set[i];
- set->status[i]
- = (set->status[i] & ~ prototol->is_set[i])
- | (prototol->status[i] & protocol->is_set[i])
- ;
- U32 protocol_copy_mask = protocol->is_set[i]
- & ~ (set->change_deprecated[i] | set->change_prohibited[i])
- ;
- set->protocol[i]
- = (set->protocol[i] & ~ protocol_copy_mask)
- | (protocol->status[i] & protocol_copy_mask)
- ;
- set->change_prohibited[i] |= protocol->change_prohibited[i];
- set->change_deprecated[i] |= protocol->change_deprecated[i];
- }
- }
- feature_t find_feature_by_name (const char *keypv, STRLEN keylen) {
- STRLEN prefix_length = sizeof("feature_") - 1;
- const char *subf = keypv + prefix_length;
- if (keylen < sizeof ("feature_"))
- return FEATURE_NOT_FOUND;
- if (! memBEGINs (keypv, keylen, "feature_"))
- return FEATURE_NOT_FOUND;
- if (((unsigned char) subf[0]) >= STATIC_ARRAY_LENGTH (feature_name_magic_lookup))
- return FEATURE_NOT_FOUND;
- // start lookup at indexed name
- for (
- enum feature_t lookup = feature_name_magic_lookup[subf[0]];
- lookup > FEATURE_NOT_FOUND;
- --lookup
- ) {
- // when out of first char group
- // includes also unknown features
- if (! feature_names[lookup].name[0] == subf[0])
- break;
- if (keylen != feature_names[lookup].length + prefix_length)
- continue;
- if (memcmp (subf + 1, feature_names[lookup].name + 1, keylen - prefix_length) != 0)
- continue;
- return lookup;
- }
- return FEATURE_NOT_FOUND;
- }
- void feature_save (features_t *features) {
- for (U32 i = 0; i < SIZEOF_ARRAY (feature_bits_t); ++i) {
- SAVEI32 (features->state[i]);
- SAVEI32 (features->is_set[i]);
- SAVEI32 (features->protocol[i]);
- SAVEI32 (features->change_deprecated[i]);
- SAVEI32 (features->change_prohibited[i]);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement