| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #ifndef __XS_PARSE_KEYWORD_H__ | 
| 2 |  |  |  |  |  |  | #define __XS_PARSE_KEYWORD_H__ | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | #define XSPARSEKEYWORD_ABI_VERSION 2 | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | struct XSParseKeywordPieceType; | 
| 7 |  |  |  |  |  |  | struct XSParseKeywordPieceType { | 
| 8 |  |  |  |  |  |  | int type; | 
| 9 |  |  |  |  |  |  | union { | 
| 10 |  |  |  |  |  |  | char                                  c;      /* LITERALCHAR */ | 
| 11 |  |  |  |  |  |  | const char                           *str;    /* LITERALSTR */ | 
| 12 |  |  |  |  |  |  | const struct XSParseKeywordPieceType *pieces; /* SCOPEs */ | 
| 13 |  |  |  |  |  |  | void                                (*callback)(pTHX_ void *hookdata); /* SETUP */ | 
| 14 |  |  |  |  |  |  | } u; | 
| 15 |  |  |  |  |  |  | }; | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | enum { | 
| 18 |  |  |  |  |  |  | XPK_FLAG_EXPR     = (1<<0), | 
| 19 |  |  |  |  |  |  | XPK_FLAG_STMT     = (1<<1), | 
| 20 |  |  |  |  |  |  | XPK_FLAG_AUTOSEMI = (1<<2), | 
| 21 |  |  |  |  |  |  | }; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | enum { | 
| 24 |  |  |  |  |  |  | /* skip zero */ | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | /*                                    emits */ | 
| 27 |  |  |  |  |  |  | XS_PARSE_KEYWORD_LITERALCHAR = 1,   /* nothing */ | 
| 28 |  |  |  |  |  |  | XS_PARSE_KEYWORD_LITERALSTR,        /* nothing */ | 
| 29 |  |  |  |  |  |  | XS_PARSE_KEYWORD_FAILURE = 0x0f,    /* nothing */ | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | XS_PARSE_KEYWORD_BLOCK = 0x10,      /* op */ | 
| 32 |  |  |  |  |  |  | XS_PARSE_KEYWORD_ANONSUB,           /* cv */ | 
| 33 |  |  |  |  |  |  | /* TODO: XS_PARSE_KEYWORD_ARITHEXPR = 0x12 */ | 
| 34 |  |  |  |  |  |  | XS_PARSE_KEYWORD_TERMEXPR = 0x13,   /* op */ | 
| 35 |  |  |  |  |  |  | XS_PARSE_KEYWORD_LISTEXPR,          /* op */ | 
| 36 |  |  |  |  |  |  | /* TODO: XS_PARSE_KEYWORD_FULLEXPR = 0x15 */ | 
| 37 |  |  |  |  |  |  | XS_PARSE_KEYWORD_IDENT = 0x16,      /* sv */ | 
| 38 |  |  |  |  |  |  | XS_PARSE_KEYWORD_PACKAGENAME,       /* sv */ | 
| 39 |  |  |  |  |  |  | XS_PARSE_KEYWORD_LEXVARNAME,        /* sv */ | 
| 40 |  |  |  |  |  |  | XS_PARSE_KEYWORD_LEXVAR,            /* padix */ | 
| 41 |  |  |  |  |  |  | XS_PARSE_KEYWORD_ATTRS,             /* i / {attr.name + attr.val} */ | 
| 42 |  |  |  |  |  |  | XS_PARSE_KEYWORD_VSTRING,           /* sv */ | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | XS_PARSE_KEYWORD_INFIX = 0x40,      /* infix */ | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | XS_PARSE_KEYWORD_SETUP = 0x70,      /* invokes callback, emits nothing */ | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | XS_PARSE_KEYWORD_SEQUENCE = 0x80,   /* contained */ | 
| 49 |  |  |  |  |  |  | XS_PARSE_KEYWORD_REPEATED,          /* i, contained */ | 
| 50 |  |  |  |  |  |  | XS_PARSE_KEYWORD_CHOICE,            /* i, contained */ | 
| 51 |  |  |  |  |  |  | XS_PARSE_KEYWORD_TAGGEDCHOICE,      /* i, contained */ | 
| 52 |  |  |  |  |  |  | XS_PARSE_KEYWORD_SEPARATEDLIST,     /* i, contained */ | 
| 53 |  |  |  |  |  |  | XS_PARSE_KEYWORD_PARENSCOPE = 0xb0, /* contained */ | 
| 54 |  |  |  |  |  |  | XS_PARSE_KEYWORD_BRACKETSCOPE,      /* contained */ | 
| 55 |  |  |  |  |  |  | XS_PARSE_KEYWORD_BRACESCOPE,        /* contained */ | 
| 56 |  |  |  |  |  |  | XS_PARSE_KEYWORD_CHEVRONSCOPE,      /* contained */ | 
| 57 |  |  |  |  |  |  | }; | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | enum { | 
| 60 |  |  |  |  |  |  | XPK_LEXVAR_SCALAR = (1<<0), | 
| 61 |  |  |  |  |  |  | XPK_LEXVAR_ARRAY  = (1<<1), | 
| 62 |  |  |  |  |  |  | XPK_LEXVAR_HASH   = (1<<2), | 
| 63 |  |  |  |  |  |  | XPK_LEXVAR_ANY    = XPK_LEXVAR_SCALAR|XPK_LEXVAR_ARRAY|XPK_LEXVAR_HASH, | 
| 64 |  |  |  |  |  |  | }; | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | enum { | 
| 67 |  |  |  |  |  |  | XPK_TYPEFLAG_OPT      = (1<<16), | 
| 68 |  |  |  |  |  |  | XPK_TYPEFLAG_SPECIAL  = (1<<17), /* on XPK_BLOCK: scoped | 
| 69 |  |  |  |  |  |  | on XPK_LEXVAR: my */ | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | /* These three are shifted versions of perl's G_VOID, G_SCALAR, G_LIST */ | 
| 72 |  |  |  |  |  |  | XPK_TYPEFLAG_G_VOID   = (1<<18), | 
| 73 |  |  |  |  |  |  | XPK_TYPEFLAG_G_SCALAR = (2<<18), | 
| 74 |  |  |  |  |  |  | XPK_TYPEFLAG_G_LIST   = (3<<18), | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | XPK_TYPEFLAG_ENTERLEAVE = (1<<20), /* wrap ENTER/LEAVE pair around the item */ | 
| 77 |  |  |  |  |  |  | }; | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | #define XPK_BLOCK_flags(flags) {.type = XS_PARSE_KEYWORD_BLOCK|(flags), .u.pieces = NULL} | 
| 80 |  |  |  |  |  |  | #define XPK_BLOCK              XPK_BLOCK_flags(0) | 
| 81 |  |  |  |  |  |  | #define XPK_BLOCK_VOIDCTX      XPK_BLOCK_flags(XPK_TYPEFLAG_SPECIAL|XPK_TYPEFLAG_G_VOID) | 
| 82 |  |  |  |  |  |  | #define XPK_BLOCK_SCALARCTX    XPK_BLOCK_flags(XPK_TYPEFLAG_SPECIAL|XPK_TYPEFLAG_G_SCALAR) | 
| 83 |  |  |  |  |  |  | #define XPK_BLOCK_LISTCTX      XPK_BLOCK_flags(XPK_TYPEFLAG_SPECIAL|XPK_TYPEFLAG_G_LIST) | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | #define XPK_PREFIXED_BLOCK_flags(flags,...) \ | 
| 86 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_BLOCK|flags, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 87 |  |  |  |  |  |  | #define XPK_PREFIXED_BLOCK(...)            XPK_PREFIXED_BLOCK_flags(0, __VA_ARGS__) | 
| 88 |  |  |  |  |  |  | #define XPK_PREFIXED_BLOCK_ENTERLEAVE(...) XPK_PREFIXED_BLOCK_flags(XPK_TYPEFLAG_ENTERLEAVE, __VA_ARGS__) | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | #define XPK_SETUP(setup)       {.type = XS_PARSE_KEYWORD_SETUP, .u.callback = setup} | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | #define XPK_ANONSUB {.type = XS_PARSE_KEYWORD_ANONSUB} | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | #define XPK_TERMEXPR_flags(flags) {.type = XS_PARSE_KEYWORD_TERMEXPR|(flags)} | 
| 95 |  |  |  |  |  |  | #define XPK_TERMEXPR              XPK_TERMEXPR_flags(0) | 
| 96 |  |  |  |  |  |  | #define XPK_TERMEXPR_VOIDCTX      XPK_TERMEXPR_flags(XPK_TYPEFLAG_G_VOID) | 
| 97 |  |  |  |  |  |  | #define XPK_TERMEXPR_SCALARCTX    XPK_TERMEXPR_flags(XPK_TYPEFLAG_G_SCALAR) | 
| 98 |  |  |  |  |  |  | #define XPK_LISTEXPR_flags(flags) {.type = XS_PARSE_KEYWORD_LISTEXPR|(flags)} | 
| 99 |  |  |  |  |  |  | #define XPK_LISTEXPR              XPK_LISTEXPR_flags(0) | 
| 100 |  |  |  |  |  |  | #define XPK_LISTEXPR_LISTCTX      XPK_LISTEXPR_flags(XPK_TYPEFLAG_G_LIST) | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | #define XPK_IDENT           {.type = XS_PARSE_KEYWORD_IDENT                       } | 
| 103 |  |  |  |  |  |  | #define XPK_IDENT_OPT       {.type = XS_PARSE_KEYWORD_IDENT      |XPK_TYPEFLAG_OPT} | 
| 104 |  |  |  |  |  |  | #define XPK_PACKAGENAME     {.type = XS_PARSE_KEYWORD_PACKAGENAME                 } | 
| 105 |  |  |  |  |  |  | #define XPK_PACKAGENAME_OPT {.type = XS_PARSE_KEYWORD_PACKAGENAME|XPK_TYPEFLAG_OPT} | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | #define XPK_LEXVARNAME(kind) {.type = XS_PARSE_KEYWORD_LEXVARNAME, .u.c = kind} | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | #define XPK_LEXVAR_MY(kind) {.type = XS_PARSE_KEYWORD_LEXVAR|XPK_TYPEFLAG_SPECIAL, .u.c = kind} | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | #define XPK_ATTRIBUTES {.type = XS_PARSE_KEYWORD_ATTRS} | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | #define XPK_VSTRING     {.type = XS_PARSE_KEYWORD_VSTRING} | 
| 114 |  |  |  |  |  |  | #define XPK_VSTRING_OPT {.type = XS_PARSE_KEYWORD_VSTRING|XPK_TYPEFLAG_OPT} | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | #define XPK_COMMA  {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = ','} | 
| 117 |  |  |  |  |  |  | #define XPK_COLON  {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = ':'} | 
| 118 |  |  |  |  |  |  | #define XPK_EQUALS {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = '='} | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | #define XPK_LITERAL(s) {.type = XS_PARSE_KEYWORD_LITERALSTR, .u.str = (const char *)s} | 
| 121 |  |  |  |  |  |  | #define XPK_STRING(s)  XPK_LITERAL(s) | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | #define XPK_INFIX(select) {.type = XS_PARSE_KEYWORD_INFIX, .u.c = select} | 
| 124 |  |  |  |  |  |  | #define XPK_INFIX_RELATION       XPK_INFIX(XPI_SELECT_RELATION) | 
| 125 |  |  |  |  |  |  | #define XPK_INFIX_EQUALITY       XPK_INFIX(XPI_SELECT_EQUALITY) | 
| 126 |  |  |  |  |  |  | #define XPK_INFIX_MATCH_NOSMART  XPK_INFIX(XPI_SELECT_MATCH_NOSMART) | 
| 127 |  |  |  |  |  |  | #define XPK_INFIX_MATCH_SMART    XPK_INFIX(XPI_SELECT_MATCH_SMART) | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | #define XPK_SEQUENCE(...) \ | 
| 130 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_SEQUENCE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 131 |  |  |  |  |  |  | /* First piece of these must be something probe-able */ | 
| 132 |  |  |  |  |  |  | #define XPK_OPTIONAL(...) \ | 
| 133 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_SEQUENCE|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 134 |  |  |  |  |  |  | #define XPK_REPEATED(...) \ | 
| 135 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_REPEATED, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 136 |  |  |  |  |  |  | /* Every piece must be probeable */ | 
| 137 |  |  |  |  |  |  | #define XPK_CHOICE(...) \ | 
| 138 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_CHOICE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 139 |  |  |  |  |  |  | /* Every piece must be probeable, and followed by XPK_TAG */ | 
| 140 |  |  |  |  |  |  | #define XPK_TAGGEDCHOICE(...) \ | 
| 141 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_TAGGEDCHOICE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0}, {0} }} | 
| 142 |  |  |  |  |  |  | #define XPK_TAG(val) \ | 
| 143 |  |  |  |  |  |  | {.type = val} | 
| 144 |  |  |  |  |  |  | #define XPK_COMMALIST(...) \ | 
| 145 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_SEPARATEDLIST, .u.pieces = (const struct XSParseKeywordPieceType []){ \ | 
| 146 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_LITERALCHAR, .u.c = ','}, __VA_ARGS__, {0}}} | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | #define XPK_FAILURE(s) {.type = XS_PARSE_KEYWORD_FAILURE, .u.str = (const char *)s} | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | #define XPK_PARENSCOPE(...) \ | 
| 151 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_PARENSCOPE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 152 |  |  |  |  |  |  | #define XPK_PARENSCOPE_OPT(...) \ | 
| 153 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_PARENSCOPE|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | #define XPK_BRACKETSCOPE(...) \ | 
| 156 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_BRACKETSCOPE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 157 |  |  |  |  |  |  | #define XPK_BRACKETSCOPE_OPT(...) \ | 
| 158 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_BRACKETSCOPE|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | #define XPK_BRACESCOPE(...) \ | 
| 161 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_BRACESCOPE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 162 |  |  |  |  |  |  | #define XPK_BRACESCOPE_OPT(...) \ | 
| 163 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_BRACESCOPE|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | #define XPK_CHEVRONSCOPE(...) \ | 
| 166 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_CHEVRONSCOPE, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 167 |  |  |  |  |  |  | #define XPK_CHEVRONSCOPE_OPT(...) \ | 
| 168 |  |  |  |  |  |  | {.type = XS_PARSE_KEYWORD_CHEVRONSCOPE|XPK_TYPEFLAG_OPT, .u.pieces = (const struct XSParseKeywordPieceType []){ __VA_ARGS__, {0} }} | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | /* This type defined in XSParseInfix.h */ | 
| 171 |  |  |  |  |  |  | typedef struct XSParseInfixInfo XSParseInfixInfo; | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | typedef struct { | 
| 174 |  |  |  |  |  |  | union { | 
| 175 |  |  |  |  |  |  | OP *op; | 
| 176 |  |  |  |  |  |  | CV *cv; | 
| 177 |  |  |  |  |  |  | SV *sv; | 
| 178 |  |  |  |  |  |  | int i; | 
| 179 |  |  |  |  |  |  | struct { SV *name; SV *value; } attr; | 
| 180 |  |  |  |  |  |  | PADOFFSET padix; | 
| 181 |  |  |  |  |  |  | XSParseInfixInfo *infix; | 
| 182 |  |  |  |  |  |  | }; | 
| 183 |  |  |  |  |  |  | int line; | 
| 184 |  |  |  |  |  |  | } XSParseKeywordPiece; | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | struct XSParseKeywordHooks { | 
| 187 |  |  |  |  |  |  | U32 flags; | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | /* used by build1 */ | 
| 190 |  |  |  |  |  |  | struct XSParseKeywordPieceType piece1; | 
| 191 |  |  |  |  |  |  | /* alternatively, used by build */ | 
| 192 |  |  |  |  |  |  | const struct XSParseKeywordPieceType *pieces; | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | /* These two hooks are ANDed together; both must pass, if present */ | 
| 195 |  |  |  |  |  |  | const char *permit_hintkey; | 
| 196 |  |  |  |  |  |  | bool (*permit) (pTHX_ void *hookdata); | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | void (*check)(pTHX_ void *hookdata); | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | /* These are alternatives; the first one defined is used */ | 
| 201 |  |  |  |  |  |  | int (*parse)(pTHX_ OP **opp, void *hookdata); | 
| 202 |  |  |  |  |  |  | int (*build)(pTHX_ OP **out, XSParseKeywordPiece *args[], size_t nargs, void *hookdata); | 
| 203 |  |  |  |  |  |  | int (*build1)(pTHX_ OP **out, XSParseKeywordPiece *arg0, void *hookdata); | 
| 204 |  |  |  |  |  |  | }; | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | static void (*register_xs_parse_keyword_func)(pTHX_ const char *kwname, const struct XSParseKeywordHooks *hooks, void *hookdata); | 
| 207 |  |  |  |  |  |  | #define register_xs_parse_keyword(kwname, hooks, hookdata)  S_register_xs_parse_keyword(aTHX_ kwname, hooks, hookdata) | 
| 208 |  |  |  |  |  |  | static void S_register_xs_parse_keyword(pTHX_ const char *kwname, const struct XSParseKeywordHooks *hooks, void *hookdata) | 
| 209 |  |  |  |  |  |  | { | 
| 210 | 15 | 50 |  |  |  |  | if(!register_xs_parse_keyword_func) | 
| 211 | 0 |  |  |  |  |  | croak("Must call boot_xs_parse_keyword() first"); | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 15 |  |  |  |  |  | (*register_xs_parse_keyword_func)(aTHX_ kwname, hooks, hookdata); | 
| 214 |  |  |  |  |  |  | } | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | #define boot_xs_parse_keyword(ver) S_boot_xs_parse_keyword(aTHX_ ver) | 
| 217 | 15 |  |  |  |  |  | static void S_boot_xs_parse_keyword(pTHX_ double ver) { | 
| 218 |  |  |  |  |  |  | SV **svp; | 
| 219 | 15 | 50 |  |  |  |  | SV *versv = ver ? newSVnv(ver) : NULL; | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 15 |  |  |  |  |  | load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("XS::Parse::Keyword"), versv, NULL); | 
| 222 |  |  |  |  |  |  |  | 
| 223 | 15 |  |  |  |  |  | svp = hv_fetchs(PL_modglobal, "XS::Parse::Keyword/ABIVERSION_MIN", 0); | 
| 224 | 15 | 50 |  |  |  |  | if(!svp) | 
| 225 | 0 |  |  |  |  |  | croak("XS::Parse::Keyword ABI minimum version missing"); | 
| 226 | 15 | 50 |  |  |  |  | int abi_ver = SvIV(*svp); | 
| 227 | 15 | 50 |  |  |  |  | if(abi_ver > XSPARSEKEYWORD_ABI_VERSION) | 
| 228 | 0 |  |  |  |  |  | croak("XS::Parse::Keyword ABI version mismatch - library supports >= %d, compiled for %d", | 
| 229 |  |  |  |  |  |  | abi_ver, XSPARSEKEYWORD_ABI_VERSION); | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 15 |  |  |  |  |  | svp = hv_fetchs(PL_modglobal, "XS::Parse::Keyword/ABIVERSION_MAX", 0); | 
| 232 | 15 | 50 |  |  |  |  | abi_ver = SvIV(*svp); | 
| 233 | 15 | 50 |  |  |  |  | if(abi_ver < XSPARSEKEYWORD_ABI_VERSION) | 
| 234 | 0 |  |  |  |  |  | croak("XS::Parse::Keyword ABI version mismatch - library supports <= %d, compiled for %d", | 
| 235 |  |  |  |  |  |  | abi_ver, XSPARSEKEYWORD_ABI_VERSION); | 
| 236 |  |  |  |  |  |  |  | 
| 237 | 15 | 50 |  |  |  |  | register_xs_parse_keyword_func = INT2PTR(void (*)(pTHX_ const char *, const struct XSParseKeywordHooks *, void *), | 
| 238 |  |  |  |  |  |  | SvUV(*hv_fetchs(PL_modglobal, "XS::Parse::Keyword/register()@2", 0))); | 
| 239 | 15 |  |  |  |  |  | } | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | #endif |