Advertisement
happy-barney

more than 32 feature bits

Mar 22nd, 2021
1,366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.02 KB | None | 0 0
  1.  
  2. // File: feature-gen.h
  3.  
  4. #define GENERATE_ALL_FEATURES()                                         \
  5.     FEATURE_DEFINE ('b', FEATURE_BAREWORD_FILEHANDLES, "bareword_filehandles") \
  6.     FEATURE_DEFINE ('b', FEATURE_BITWISE,              "bitwise")       \
  7.     FEATURE_DEFINE ('e', FEATURE_EVALBYTES,            "evalbytes")     \
  8.     FEATURE_DEFINE ('f', FEATURE_FC,                   "fc")            \
  9.     FEATURE_DEFINE ('i', FEATURE_INDIRECT,             "indirect")      \
  10.     FEATURE_DEFINE ('i', FEATURE_ISA,                  "isa")           \
  11.     FEATURE_DEFINE ('m', FEATURE_MULTIDIMENSIONAL,     "multidimensional") \
  12.     FEATURE_DEFINE ('m', FEATURE_MYREF,                "myref")         \
  13.     FEATURE_DEFINE ('p', FEATURE_POSTDEREF_QQ,         "postderef_qq")  \
  14.     FEATURE_DEFINE ('r', FEATURE_REFALIASING,          "refaliasing")   \
  15.     FEATURE_DEFINE ('s', FEATURE_SAY,                  "say")           \
  16.     FEATURE_DEFINE ('s', FEATURE_SIGNATURES,           "signatures")    \
  17.     FEATURE_DEFINE ('s', FEATURE_STATE,                "state")         \
  18.     FEATURE_DEFINE ('s', FEATURE_SWITCH,               "switch")        \
  19.     FEATURE_DEFINE ('t', FEATURE_TRY,                  "try")           \
  20.     FEATURE_DEFINE ('u', FEATURE_UNICODE,              "unicode")       \
  21.     FEATURE_DEFINE ('u', FEATURE_UNIEVAL,              "unieval")       \
  22.     FEATURE_DEFINE ('_', FEATURE___SUB__,              "__SUB__")
  23.  
  24. #define GENERATE_ALL_FEATURE_BUNDLES()                                  \
  25.     BUNDLE_DEFINE ( FEATURE_BUNDLE_DEFAULT, (                           \
  26.         BUNDLE_ENABLE (FEATURE_INDIRECT)                                \
  27.         BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL)                        \
  28.         BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)                    \
  29.     ))                                                                  \
  30.     BUNDLE_DEFINE ( FEATURE_BUNDLE_510, (                               \
  31.         BUNDLE_ENABLE (FEATURE_INDIRECT)                                \
  32.         BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL)                        \
  33.         BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)                    \
  34.         BUNDLE_ENABLE (FEATURE_SAY)                                     \
  35.         BUNDLE_ENABLE (FEATURE_STATE)                                   \
  36.         BUNDLE_ENABLE (FEATURE_SWITCH)                                  \
  37.     ))                                                                  \
  38.     BUNDLE_DEFINE ( FEATURE_BUNDLE_511, (                               \
  39.         BUNDLE_ENABLE (FEATURE_INDIRECT)                                \
  40.         BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL)                        \
  41.         BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)                    \
  42.         BUNDLE_ENABLE (FEATURE_SAY)                                     \
  43.         BUNDLE_ENABLE (FEATURE_STATE)                                   \
  44.         BUNDLE_ENABLE (FEATURE_SWITCH)                                  \
  45.         BUNDLE_ENABLE (FEATURE_UNICODE)                                 \
  46.     ))                                                                  \
  47.     BUNDLE_DEFINE ( FEATURE_BUNDLE_515, (                               \
  48.         BUNDLE_ENABLE (FEATURE_INDIRECT)                                \
  49.         BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL)                        \
  50.         BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)                    \
  51.         BUNDLE_ENABLE (FEATURE_SAY)                                     \
  52.         BUNDLE_ENABLE (FEATURE_STATE)                                   \
  53.         BUNDLE_ENABLE (FEATURE_SWITCH)                                  \
  54.         BUNDLE_ENABLE (FEATURE_UNICODE)                                 \
  55.         BUNDLE_ENABLE (FEATURE_UNIEVAL)                                 \
  56.         BUNDLE_ENABLE (FEATURE_EVALBYTES)                               \
  57.         BUNDLE_ENABLE (FEATURE___SUB__)                                 \
  58.         BUNDLE_ENABLE (FEATURE_FC)                                      \
  59.     ))                                                                  \
  60.     BUNDLE_DEFINE ( FEATURE_BUNDLE_523, (                               \
  61.         BUNDLE_ENABLE (FEATURE_INDIRECT)                                \
  62.         BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL)                        \
  63.         BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)                    \
  64.         BUNDLE_ENABLE (FEATURE_SAY)                                     \
  65.         BUNDLE_ENABLE (FEATURE_STATE)                                   \
  66.         BUNDLE_ENABLE (FEATURE_SWITCH)                                  \
  67.         BUNDLE_ENABLE (FEATURE_UNICODE)                                 \
  68.         BUNDLE_ENABLE (FEATURE_UNIEVAL)                                 \
  69.         BUNDLE_ENABLE (FEATURE_EVALBYTES)                               \
  70.         BUNDLE_ENABLE (FEATURE___SUB__)                                 \
  71.         BUNDLE_ENABLE (FEATURE_FC)                                      \
  72.         BUNDLE_ENABLE (FEATURE_POSTDEREF_QQ)                            \
  73.     ))                                                                  \
  74.     BUNDLE_DEFINE ( FEATURE_BUNDLE_527, (                               \
  75.         BUNDLE_ENABLE (FEATURE_INDIRECT)                                \
  76.         BUNDLE_ENABLE (FEATURE_MULTIDIMENSIONAL)                        \
  77.         BUNDLE_ENABLE (FEATURE_BAREWORD_FILEHANDLES)\                   \
  78.         BUNDLE_ENABLE (FEATURE_SAY)                                     \
  79.         BUNDLE_ENABLE (FEATURE_STATE)                                   \
  80.         BUNDLE_ENABLE (FEATURE_SWITCH)                                  \
  81.         BUNDLE_ENABLE (FEATURE_UNICODE)                                 \
  82.         BUNDLE_ENABLE (FEATURE_UNIEVAL)                                 \
  83.         BUNDLE_ENABLE (FEATURE_EVALBYTES)                               \
  84.         BUNDLE_ENABLE (FEATURE___SUB__)                                 \
  85.         BUNDLE_ENABLE (FEATURE_FC)                                      \
  86.         BUNDLE_ENABLE (FEATURE_POSTDEREF_QQ)                            \
  87.         BUNDLE_ENABLE (FEATURE_BITWISE)                                 \
  88.     ))                                                                  \
  89.     BUNDLE_DEFINE ( FEATURE_BUNDLE_700, (                               \
  90.         BUNDLE_DEPRECATE (FEATURE_INDIRECT)                             \
  91.         BUNDLE_PROHIBIT (FEATURE_MULTIDIMENSIONAL)                      \
  92.         BUNDLE_PROHIBIT (FEATURE_BAREWORD_FILEHANDLES)                  \
  93.         BUNDLE_ENABLE (FEATURE_SAY)                                     \
  94.         BUNDLE_ENABLE (FEATURE_STATE)                                   \
  95.         BUNDLE_ENABLE (FEATURE_SWITCH)                                  \
  96.         BUNDLE_ENABLE (FEATURE_UNICODE)                                 \
  97.         BUNDLE_ENABLE (FEATURE_UNIEVAL)                                 \
  98.         BUNDLE_ENABLE (FEATURE_EVALBYTES)                               \
  99.         BUNDLE_ENABLE (FEATURE___SUB__)                                 \
  100.         BUNDLE_ENABLE (FEATURE_FC)                                      \
  101.         BUNDLE_ENABLE (FEATURE_POSTDEREF_QQ)                            \
  102.         BUNDLE_ENABLE (FEATURE_BITWISE)                                 \
  103.     ))
  104.  
  105. // End of file: feature-gen.h
  106.  
  107. // File: feature.h
  108.  
  109. typedef enum feature_t {
  110.     FEATURE_NOT_FOUND = -1,
  111.  
  112.     #define FEATURE_DEFINE(Bucket, Symbol, Name) Symbol,
  113.     GENERATE_ALL_FEATURES()
  114.     #undef FEATURE_DEFINE
  115.  
  116.     NUMBER_OF_FEATURES
  117. } feature_t;
  118.  
  119. typedef struct feature_name_t {
  120.     STRLEN length;
  121.     const char *name;
  122. } feature_name_t;
  123.  
  124. typedef U32 features_bits_t[ 1 + ((NUMBER_OF_FEATURES - 1) >> 5) ];
  125. typedef struct features_t {
  126.     // current
  127.     features_bits_t state;
  128.  
  129.     // protocol enhancement
  130.     features_bits_t is_set;
  131.     features_bits_t protocol;
  132.     features_bits_t change_deprecated;
  133.     features_bits_t change_prohibited;
  134. } features_t;
  135.  
  136. typedef struct feature_protocol_t {
  137.     features_bits_t state;
  138.     features_bits_t change_deprecated;
  139.     features_bits_t change_prohibited;
  140. } feature_protocol_t;
  141.  
  142. #define BUNDLE_DEFINE(Name, Content)                                    \
  143.     extern const feature_protocol_t const * FEATURE_BUNDLE_ ## Name;
  144.  
  145. GENERATE_ALL_FEATURE_BUNDLES()
  146.  
  147. #undef BUNDLE_DEFINE
  148.  
  149. bool feature_is_enabled (features_t *set, feature_t feature);
  150. void feature_set_value (features_t *set, feature_t feature, bool value);
  151. void feature_set_bundle (features_t *set, feature_protocol_t *bundle);
  152.  
  153. feature_t find_feature_by_name (const char *keypv, STRLEN keylen);
  154.  
  155. // modified existing generated code
  156. #define magic_sethint_feature(keysv, keypv, keylen, valsv, valbool) \
  157.     S_magic_sethint_feature(aTHX_ (keysv), (keypv), (keylen), (valsv), (valbool))
  158.  
  159. PERL_STATIC_INLINE void
  160. S_magic_sethint_feature(pTHX_ SV *keysv, const char *keypv, STRLEN keylen,
  161.                         SV *valsv, bool valbool) {
  162.     if (keysv)
  163.       keypv = SvPV_const(keysv, keylen);
  164.  
  165.     feature_t feature = find_feature_by_name (keypv, keylen);
  166.     if (feature > FEATURE_NOT_FOUND)
  167.         feature_set (PL_compiling.cop_features, feature, valsv ? SvTRUE(valsv) : valbool);
  168. }
  169.  
  170. // End of file: feature.h
  171.  
  172. // File: feature.c
  173.  
  174. static feature_name_t feature_names[] = {
  175. #   define FEATURE_DEFINE(Bucket, Symbol, Name)                   \
  176.         [Symbol] = ( (feature_name_t) { .length = sizeof (Name) - 1, .name = Name } ),
  177.  
  178.     GENERATE_ALL_FEATURES()
  179.  
  180. #   undef FEATURE_DEFINE
  181. };
  182.  
  183. static feature_t feature_name_lookup[] = {
  184. #   define FEATURE_DEFINE(Bucket, Symbol, Name) [Bucket] = Symbol,
  185.  
  186.     GENERATE_ALL_FEATURES()
  187.  
  188. #   undef FEATURE_DEFINE
  189. };
  190.  
  191. #define FEATURE_OFFSET(Feature)                                         \
  192.     ((Feature) >> 5)
  193.  
  194. #define FEATURE_MASK(Feature)                                           \
  195.     (1 << ((Feature) & 0x1f))
  196.  
  197. #define SIZEOF_ARRAY(Array)                                             \
  198.     (sizeof (Array) / sizeof ( ((Array) {})[0]))
  199.  
  200.  
  201. bool feature_is_enabled (features_t *set, feature_t feature) {
  202.     U32 mask = FEATURE_MASK (feature);
  203.     U32 offset = FEATURE_OFFSET (feature);
  204.  
  205.     return set->is_set[offset] & mask ? 1 : 0;
  206. }
  207.  
  208. void feature_set_value (features_t *set, feature_t feature, bool value) {
  209.     U32 mask = FEATURE_MASK (feature);
  210.     U32 offset = FEATURE_OFFSET (feature);
  211.     U32 new_value = value ? mask : 0;
  212.  
  213.     if (set->protocol[offset] & mask != new_value) {
  214.         if (set->change_prohibited[offset] & mask) {
  215.             // die
  216.             return;
  217.         }
  218.  
  219.         if (set->change_deprecated[offset] & mask) {
  220.             // warn
  221.         }
  222.     }
  223.  
  224.     set->is_set[offset] |= mask;
  225.     if (value)
  226.         set->state[offset] |= mask;
  227.     else
  228.         set->state[offset] &= ~mask;
  229. }
  230.  
  231. void feature_set_bundle (features_t *set, feature_protocol_t *bundle) {
  232.     // bundle just copies its definition over current
  233.     bzero (set->is_set, sizeof (set->is_set));
  234.     memcpy (set->bundle, bundle->state, sizeof (bundle->state));
  235. }
  236.  
  237. void feature_set_protocol (features_t *set, feature_protocol_t *protocol) {
  238.     // protocol merges deprecated and prohibited with current
  239.     // and modifies only those explicitly mentioned
  240.     // ie:
  241.     // use feature 'fc';
  242.     // use v5.10;
  243.     // ... fc still available
  244.  
  245.     for (U32 i = 0; i < SIZEOF_ARRAY (feature_bits_t); ++i) {
  246.         U32 mask = set->change_prohibited[i] & protocol->is_set[i];
  247.         if (mask && ((set->protocol[i] & mask) ^ (protocol->state & mask))) {
  248.             // current protocol prohibits some bits that new protocol is about to change
  249.             // do not set any feature before checking all
  250.             report error and return;
  251.         }
  252.     }
  253.  
  254.     for (U32 i = 0; i < SIZEOF_ARRAY (feature_bits_t); ++i) {
  255.         U32 mask = set->change_deprecated[i] & protocol->is_set[i];
  256.         if (mask && ((set->protocol[i] & mask) ^ (protocol->state & mask))) {
  257.             // current protocol prohibits some bits that new protocol is about to change
  258.             warn;
  259.         }
  260.  
  261.         // clear is_set bits - bundle overrides them
  262.         set->is_set[i] &= ~ protocol->is_set[i];
  263.  
  264.         set->status[i]
  265.             = (set->status[i] & ~ prototol->is_set[i])
  266.             | (prototol->status[i] & protocol->is_set[i])
  267.             ;
  268.  
  269.         U32 protocol_copy_mask = protocol->is_set[i]
  270.             & ~ (set->change_deprecated[i] | set->change_prohibited[i])
  271.             ;
  272.  
  273.         set->protocol[i]
  274.             = (set->protocol[i] & ~ protocol_copy_mask)
  275.             | (protocol->status[i] & protocol_copy_mask)
  276.             ;
  277.  
  278.         set->change_prohibited[i] |= protocol->change_prohibited[i];
  279.         set->change_deprecated[i] |= protocol->change_deprecated[i];
  280.     }
  281. }
  282.  
  283. feature_t find_feature_by_name (const char *keypv, STRLEN keylen) {
  284.     STRLEN prefix_length = sizeof("feature_") - 1;
  285.     const char *subf = keypv + prefix_length;
  286.  
  287.     if (keylen < sizeof ("feature_"))
  288.         return FEATURE_NOT_FOUND;
  289.  
  290.     if (! memBEGINs (keypv, keylen, "feature_"))
  291.         return FEATURE_NOT_FOUND;
  292.  
  293.     if (((unsigned char) subf[0]) >= STATIC_ARRAY_LENGTH (feature_name_magic_lookup))
  294.         return FEATURE_NOT_FOUND;
  295.  
  296.     // start lookup at indexed name
  297.     for (
  298.          enum feature_t lookup = feature_name_magic_lookup[subf[0]];
  299.          lookup > FEATURE_NOT_FOUND;
  300.          --lookup
  301.     ) {
  302.         // when out of first char group
  303.         // includes also unknown features
  304.         if (! feature_names[lookup].name[0] == subf[0])
  305.             break;
  306.  
  307.         if (keylen != feature_names[lookup].length + prefix_length)
  308.             continue;
  309.  
  310.         if (memcmp (subf + 1, feature_names[lookup].name + 1, keylen - prefix_length) != 0)
  311.             continue;
  312.  
  313.         return lookup;
  314.     }
  315.  
  316.     return FEATURE_NOT_FOUND;
  317. }
  318.  
  319. void feature_save (features_t *features) {
  320.     for (U32 i = 0; i < SIZEOF_ARRAY (feature_bits_t); ++i) {
  321.         SAVEI32 (features->state[i]);
  322.         SAVEI32 (features->is_set[i]);
  323.         SAVEI32 (features->protocol[i]);
  324.         SAVEI32 (features->change_deprecated[i]);
  325.         SAVEI32 (features->change_prohibited[i]);
  326.     }
  327. }
  328.  
  329.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement