7 #include "php_scandir.h"
11 PSI_Context
*PSI_ContextInit(PSI_Context
*C
, PSI_ContextOps
*ops
, PSI_ContextErrorFunc error
)
14 C
= malloc(sizeof(*C
));
16 memset(C
, 0, sizeof(*C
));
25 static int psi_select_dirent(const struct dirent
*entry
)
28 #define FNM_CASEFOLD 0
30 return 0 == fnmatch("*.psi", entry
->d_name
, FNM_CASEFOLD
);
34 void PSI_ContextBuild(PSI_Context
*C
, const char *path
)
37 struct dirent
**entries
= NULL
;
39 n
= php_scandir(path
, &entries
, psi_select_dirent
, alphasort
);
42 C
->error(PSI_WARNING
, "Failed to scan PSI directory '%s'", path
);
43 } else for (i
= 0; i
< n
; ++i
) {
48 if (MAXPATHLEN
<= slprintf(psi
, MAXPATHLEN
, "%s/%s", path
, entries
[i
]->d_name
)) {
49 C
->error(PSI_WARNING
, "Path to PSI file too long: %s/%s",
50 path
, entries
[i
]->d_name
);
52 if (!PSI_ParserInit(&P
, psi
, C
->error
, 0)) {
53 C
->error(PSI_WARNING
, "Failed to init PSI parser (%s): %s",
54 psi
, strerror(errno
));
58 while (-1 != PSI_ParserScan(&P
)) {
59 PSI_ParserParse(&P
, PSI_TokenAlloc(&P
));
61 PSI_ParserParse(&P
, NULL
);
63 if (!PSI_ValidatorInit(&V
, &P
)) {
64 C
->error(PSI_WARNING
, "Failed to init PSI validator");
69 if (PSI_ValidatorValidate(&V
)) {
70 zend_function_entry
*closures
= PSI_ContextCompile(C
, (PSI_Data
*) &V
);
72 if (closures
&& SUCCESS
!= zend_register_functions(NULL
, closures
, NULL
, MODULE_PERSISTENT
)) {
73 C
->error(PSI_WARNING
, "Failed to register functions!");
77 PSI_ValidatorDtor(&V
);
80 for (i
= 0; i
< n
; ++i
) {
88 zend_function_entry
*PSI_ContextCompile(PSI_Context
*C
, PSI_Data
*D
)
90 size_t count
= C
->count
++;
91 zend_function_entry
*zfe
;
93 C
->data
= realloc(C
->data
, C
->count
* sizeof(*C
->data
));
94 PSI_DataExchange(&C
->data
[count
], D
);
96 zfe
= C
->ops
->compile(C
, &C
->data
[count
]);
98 C
->closures
= realloc(C
->closures
, C
->count
* sizeof(*C
->closures
));
99 C
->closures
[count
] = zfe
;
104 void PSI_ContextDtor(PSI_Context
*C
)
110 for (i
= 0; i
< C
->count
; ++i
) {
111 PSI_DataDtor(&C
->data
[i
]);
115 memset(C
, 0, sizeof(*C
));
118 void PSI_ContextFree(PSI_Context
**C
)