11 #include "php_scandir.h"
14 #include "validator.h"
16 #define psi_predef_count(of) ((sizeof(psi_predef ##of## s)/sizeof(psi_predef ##of))-1)
17 typedef struct psi_predef_type
{
19 const char *type_name
;
22 static const psi_predef_type psi_predef_types
[] = {
25 #define psi_predef_type_count() psi_predef_count(_type)
27 typedef struct psi_predef_const
{
29 const char *type_name
;
34 static const psi_predef_const psi_predef_consts
[] = {
37 #define psi_predef_const_count() psi_predef_count(_const)
39 typedef struct psi_predef_struct_member
{
41 const char *type_name
;
47 } psi_predef_struct_member
;
48 #define PSI_PREDEF_STRUCT_MEMBERS 32
49 typedef struct psi_predef_struct
{
51 psi_predef_struct_member members
[PSI_PREDEF_STRUCT_MEMBERS
];
53 static const psi_predef_struct psi_predef_structs
[] = {
56 #define psi_predef_struct_count() psi_predef_count(_struct)
58 PSI_Context
*PSI_ContextInit(PSI_Context
*C
, PSI_ContextOps
*ops
, PSI_ContextErrorFunc error
)
64 C
= malloc(sizeof(*C
));
66 memset(C
, 0, sizeof(*C
));
72 memset(&data
, 0, sizeof(data
));
73 for (i
= 0; i
< psi_predef_type_count(); ++i
) {
74 const psi_predef_type
*pre
= &psi_predef_types
[i
];
75 decl_type
*type
= init_decl_type(pre
->type_tag
, pre
->type_name
);
76 decl_typedef
*def
= init_decl_typedef(pre
->alias
, type
);
78 data
.defs
= add_decl_typedef(data
.defs
, def
);
80 for (i
= 0; i
< psi_predef_const_count(); ++i
) {
81 const psi_predef_const
*pre
= &psi_predef_consts
[i
];
82 impl_def_val
*val
= init_impl_def_val(pre
->val_type_tag
, pre
->val_text
);
83 const_type
*type
= init_const_type(pre
->type_tag
, pre
->type_name
);
84 constant
*constant
= init_constant(type
, pre
->name
, val
);
86 data
.consts
= add_constant(data
.consts
, constant
);
88 for (i
= 0; i
< psi_predef_struct_count(); ++i
) {
89 const psi_predef_struct
*pre
= &psi_predef_structs
[i
];
90 decl_args
*dargs
= init_decl_args(NULL
);
92 for (j
= 0; j
< PSI_PREDEF_STRUCT_MEMBERS
; ++j
) {
93 const psi_predef_struct_member
*member
= &pre
->members
[j
];
101 type
= init_decl_type(member
->type_tag
, member
->type_name
);
102 dvar
= init_decl_var(member
->name
, member
->pointer_level
, member
->array_size
);
103 dargs
= add_decl_arg(dargs
, init_decl_arg(type
, dvar
));
106 data
.structs
= add_decl_struct(data
.structs
,
107 init_decl_struct(pre
->name
, dargs
));
112 static int psi_select_dirent(const struct dirent
*entry
)
115 #define FNM_CASEFOLD 0
117 return 0 == fnmatch("*.psi", entry
->d_name
, FNM_CASEFOLD
);
121 void PSI_ContextBuild(PSI_Context
*C
, const char *path
)
124 struct dirent
**entries
= NULL
;
126 n
= php_scandir(path
, &entries
, psi_select_dirent
, alphasort
);
130 } else for (i
= 0; i
< n
; ++i
) {
131 char psi
[MAXPATHLEN
];
135 if (MAXPATHLEN
<= slprintf(psi
, MAXPATHLEN
, "%s/%s", path
, entries
[i
]->d_name
)) {
136 C
->error(PSI_WARNING
, "Path to PSI file too long: %s/%s",
137 path
, entries
[i
]->d_name
);
139 if (!PSI_ParserInit(&P
, psi
, C
->error
, 0)) {
140 C
->error(PSI_WARNING
, "Failed to init PSI parser (%s): %s",
141 psi
, strerror(errno
));
145 while (-1 != PSI_ParserScan(&P
)) {
146 PSI_ParserParse(&P
, PSI_TokenAlloc(&P
));
148 PSI_ParserParse(&P
, NULL
);
150 if (!PSI_ValidatorInit(&V
, &P
)) {
151 C
->error(PSI_WARNING
, "Failed to init PSI validator");
156 if (PSI_ValidatorValidate(&V
)) {
157 zend_function_entry
*closures
;
159 closures
= PSI_ContextCompile(C
, (PSI_Data
*) &V
);
160 if (closures
&& SUCCESS
!= zend_register_functions(NULL
, closures
, NULL
, MODULE_PERSISTENT
)) {
161 C
->error(PSI_WARNING
, "Failed to register functions!");
164 PSI_ValidatorDtor(&V
);
167 for (i
= 0; i
< n
; ++i
) {
175 zend_function_entry
*PSI_ContextCompile(PSI_Context
*C
, PSI_Data
*D
)
177 size_t i
, count
= C
->count
++;
178 zend_function_entry
*zfe
;
183 zc
.flags
= CONST_PERSISTENT
|CONST_CS
;
184 zc
.module_number
= EG(current_module
)->module_number
;
186 for (i
= 0; i
< D
->consts
->count
; ++i
) {
187 constant
*c
= D
->consts
->list
[i
];
189 zc
.name
= zend_string_init(c
->name
+ (c
->name
[0] == '\\'), strlen(c
->name
) - (c
->name
[0] == '\\'), 1);
190 ZVAL_NEW_STR(&zc
.value
, zend_string_init(c
->val
->text
, strlen(c
->val
->text
), 1));
192 switch (c
->type
->type
) {
194 convert_to_boolean(&zc
.value
);
197 convert_to_long(&zc
.value
);
200 convert_to_double(&zc
.value
);
203 zend_register_constant(&zc
);
207 C
->data
= realloc(C
->data
, C
->count
* sizeof(*C
->data
));
208 PSI_DataExchange(&C
->data
[count
], D
);
210 zfe
= C
->ops
->compile(C
, &C
->data
[count
]);
212 C
->closures
= realloc(C
->closures
, C
->count
* sizeof(*C
->closures
));
213 C
->closures
[count
] = zfe
;
218 void PSI_ContextDtor(PSI_Context
*C
)
224 for (i
= 0; i
< C
->count
; ++i
) {
225 PSI_DataDtor(&C
->data
[i
]);
227 free(C
->closures
[i
]);
233 memset(C
, 0, sizeof(*C
));
236 void PSI_ContextFree(PSI_Context
**C
)