5d9d7e42f00dd9574fd9548bd8b65a696cfaa889
1 /*******************************************************************************
2 Copyright (c) 2018, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
29 # include "php_config.h"
40 HashTable psi_builtins
;
42 static bool has_include(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
43 static bool has_include_next(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
44 static bool has_feature(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
45 static bool builtin_constant_p(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
46 static bool BASE_FILE__(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
47 static bool COUNTER__(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
48 static bool FILE__(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
49 static bool INCLUDE_LEVEL__(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
50 static bool LINE__(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
51 static bool TIMESTAMP__(struct psi_cpp
*cpp
, struct psi_token
*target
, struct psi_plist
**args
, struct psi_plist
**res
);
53 static inline struct psi_plist
*builtin_sig(token_t typ
, ...)
55 struct psi_plist
*sig
;
59 if (typ
== (token_t
) - 1) {
63 sig
= psi_plist_init((psi_plist_dtor
) psi_token_free
);
67 struct psi_token
*arg
;
69 arg
= psi_token_init(typ
, &a
, 1, 0, 0, zend_empty_string
);
70 sig
= psi_plist_add(sig
, &arg
);
71 typ
= va_arg(args
, token_t
);
78 static void free_builtin(zval
*p
)
80 struct psi_builtin
*b
= Z_PTR_P(p
);
83 zend_string_release(b
->name
);
84 psi_cpp_macro_decl_free(&b
->decl
);
89 PHP_MINIT_FUNCTION(psi_builtin
);
90 PHP_MINIT_FUNCTION(psi_builtin
)
92 #define PSI_BUILTIN(builtin, ...) do { \
93 struct psi_builtin entry; \
94 struct psi_plist *sig = builtin_sig(__VA_ARGS__, 0); \
95 struct psi_cpp_macro_decl *decl = psi_cpp_macro_decl_init(sig, NULL, NULL); \
96 decl->token = psi_token_init(PSI_T_NAME, "__" #builtin, sizeof("__" #builtin)-1, \
97 0, 0, zend_empty_string); \
98 entry.name = zend_string_copy(decl->token->text); \
99 entry.func = &builtin; \
101 zend_hash_add_mem(&psi_builtins, entry.name, &entry, sizeof(entry)); \
104 zend_hash_init(&psi_builtins
, 0, NULL
, free_builtin
, 1);
105 PSI_BUILTIN(has_include
, PSI_T_CPP_HEADER
);
106 PSI_BUILTIN(has_include_next
, PSI_T_CPP_HEADER
);
107 PSI_BUILTIN(has_feature
, PSI_T_NAME
);
108 PSI_BUILTIN(builtin_constant_p
, PSI_T_NAME
);
110 PSI_BUILTIN(BASE_FILE__
, -1);
111 PSI_BUILTIN(COUNTER__
, -1);
112 PSI_BUILTIN(FILE__
, -1);
113 PSI_BUILTIN(INCLUDE_LEVEL__
, -1);
114 PSI_BUILTIN(LINE__
, -1);
115 PSI_BUILTIN(TIMESTAMP__
, -1);
120 PHP_MSHUTDOWN_FUNCTION(psi_builtin
);
121 PHP_MSHUTDOWN_FUNCTION(psi_builtin
)
123 zend_hash_destroy(&psi_builtins
);
127 bool psi_builtin_exists(zend_string
*name
)
129 return zend_hash_exists(&psi_builtins
, name
);
132 struct psi_builtin
*psi_builtin_get(zend_string
*name
)
134 return zend_hash_find_ptr(&psi_builtins
, name
);
137 static bool has_include(struct psi_cpp
*cpp
, struct psi_token
*target
,
138 struct psi_plist
**args
, struct psi_plist
**res
)
140 struct psi_plist
*arg
= args
[0];
141 struct psi_token
*tok
;
143 switch (psi_plist_count(arg
)) {
145 if (psi_plist_get(arg
, 0, &tok
)) {
146 const char *cpp_search
= cpp
->search
;
147 bool has
= psi_cpp_has_include(cpp
, tok
, 0, NULL
);
148 cpp
->search
= cpp_search
;
153 cpp
->parser
->error(PSI_DATA(cpp
->parser
), target
, PSI_WARNING
,
154 "Erroneous usage of builtin __%s", __FUNCTION__
);
159 static bool has_include_next(struct psi_cpp
*cpp
, struct psi_token
*target
,
160 struct psi_plist
**args
, struct psi_plist
**res
)
162 struct psi_plist
*arg
= args
[0];
163 struct psi_token
*tok
;
165 switch (psi_plist_count(arg
)) {
167 if (psi_plist_get(arg
, 0, &tok
)) {
168 const char *cpp_search
= cpp
->search
;
169 bool has
= psi_cpp_has_include(cpp
, tok
, PSI_CPP_INCLUDE_NEXT
, NULL
);
170 cpp
->search
= cpp_search
;
175 cpp
->parser
->error(PSI_DATA(cpp
->parser
), target
, PSI_WARNING
,
176 "Erroneous usage of builtin __%s", __FUNCTION__
);
181 static bool has_feature(struct psi_cpp
*cpp
, struct psi_token
*target
,
182 struct psi_plist
**args
, struct psi_plist
**res_ptr
)
187 static bool builtin_constant_p(struct psi_cpp
*cpp
, struct psi_token
*target
,
188 struct psi_plist
**args
, struct psi_plist
**res_ptr
)
190 /* we want functions, not macros for e.g. htonl() */
194 #define NEW_TOKEN(typ, str, len) \
195 psi_token_init((typ), (str), (len), (target)->col, (target)->line, (target)->file)
197 #define ADD_TOKEN(tok) do { \
198 struct psi_token *tok__ = tok; \
200 *res = psi_plist_init((psi_plist_dtor) psi_token_free); \
202 *res = psi_plist_add(*res, &tok__); \
205 #define ADD_QUOTED_STRING(buf, len) do { \
206 ADD_TOKEN(NEW_TOKEN(PSI_T_QUOTED_STRING, buf, len)); \
209 #define ADD_QUOTED_ZSTRING(zs) do { \
210 zend_string *zs_ = zs; \
211 ADD_QUOTED_STRING(zs_->val, zs_->len); \
214 #define ADD_UNSIGNED_NUMBER(u) do { \
217 size_t len = sprintf(buf, "%u", u_); \
218 struct psi_token *tok_ = NEW_TOKEN(PSI_T_NUMBER, buf, len); \
219 tok_->flags |= PSI_NUMBER_INT | PSI_NUMBER_U; \
223 static bool BASE_FILE__(struct psi_cpp
*cpp
, struct psi_token
*target
,
224 struct psi_plist
**args
, struct psi_plist
**res
)
226 ADD_QUOTED_ZSTRING(cpp
->parser
->input
->file
);
230 static bool COUNTER__(struct psi_cpp
*cpp
, struct psi_token
*target
,
231 struct psi_plist
**args
, struct psi_plist
**res
)
233 ADD_UNSIGNED_NUMBER(cpp
->counter
++);
237 static bool FILE__(struct psi_cpp
*cpp
, struct psi_token
*target
,
238 struct psi_plist
**args
, struct psi_plist
**res
)
240 ADD_QUOTED_ZSTRING(target
->file
);
244 static bool INCLUDE_LEVEL__(struct psi_cpp
*cpp
, struct psi_token
*target
,
245 struct psi_plist
**args
, struct psi_plist
**res
)
247 ADD_UNSIGNED_NUMBER(cpp
->include_level
);
251 static bool LINE__(struct psi_cpp
*cpp
, struct psi_token
*target
,
252 struct psi_plist
**args
, struct psi_plist
**res
)
254 ADD_UNSIGNED_NUMBER(target
->line
);
258 static bool TIMESTAMP__(struct psi_cpp
*cpp
, struct psi_token
*target
,
259 struct psi_plist
**args
, struct psi_plist
**res
)
264 str
= ctime_r(&cpp
->parser
->input
->lmod
, buf
);
266 str
= ctime(&cpp
->parser
->input
->lmod
);
270 ADD_QUOTED_STRING(str
, 24);
276 #include <libkern/OSByteOrder.h>
277 # define bswap_16(u) _OSSwapInt16(u)
278 # define bswap_32(u) _OSSwapInt32(u)
279 # define bswap_64(u) _OSSwapInt64(u)
280 #elif defined(__FreeBSD__)
281 # include <sys/endian.h>
282 # define bswap_16(u) bswap16(u)
283 # define bswap_32(u) bswap32(u)
284 # define bswap_64(u) bswap64(u)
285 #elif defined(__OpenBSD__)
286 # include <sys/types.h>
287 # define bswap_16(u) swap16(u)
288 # define bswap_32(u) swap32(u)
289 # define bswap_64(u) swap64(u)
290 #elif defined(__NetBSD__)
291 # include <sys/types.h>
292 # include <machine/bswap.h>
293 # define bswap_16(u) bswap16(u)
294 # define bswap_32(u) bswap32(u)
295 # define bswap_64(u) bswap64(u)
297 # include <byteswap.h>
300 uint16_t psi_swap16(uint16_t u
)
305 uint32_t psi_swap32(uint32_t u
)
310 uint64_t psi_swap64(uint64_t u
)