Add gen-class-map.cpp for bootstrapping constants.h and class_map.cpp
Conversion of PHP versions so we don't need PHP to build HHVM For the most part, the generated files haven't changed from the PHP sourced versions (apart from minor indentation and whitespace changes). Except for one major exception: An IDL's function/method argument list includes a "value" field for default parameters which takes psuedo-serialized values in several forms. Most are simple scalarish values like: "true", "null", "null_array", "null_variant", "123", "0x456", "0123", "1.23", "\"foo\"" However referencing other constants is also supported: "k_FOO", "q_Bar$$BAZ" Or even bitmask compositions like: "k_FOO|k_BAR|k_BAZ" Runtime uses of these values are encoded directly into *.ext_hhvm.cpp files, so they reach userspace code just fine. The value placed in g_class_map are used exclusively by ext_reflection to allow introspection at runtime. Under the old class_map.php parameter default constant references would be resolved in a (somewhat buggy) eval(), since we don't have eval within gen-class-map, we reuse the kUnserializable deferral. This diff provides a mechanism to resolve this in ReflectionMethod uses (an improvement from previous behavior), and leaves the current eval-on-demand behavior for ReflectionFunction. These two code paths are different due to the partial state of migration away from using ClassInfo.
Esse commit está contido em:
@@ -22,7 +22,7 @@ SET(USE_HHVM TRUE)
|
||||
SET(ENV{HHVM} 1)
|
||||
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
|
||||
|
||||
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/vm system util)
|
||||
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/vm util)
|
||||
foreach (dir ${RECURSIVE_SOURCE_SUBDIRS})
|
||||
|
||||
auto_sources(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
|
||||
@@ -96,6 +96,7 @@ add_subdirectory("tools/gen-ext-hhvm")
|
||||
add_subdirectory(compiler)
|
||||
add_subdirectory(runtime/ext_hhvm)
|
||||
add_subdirectory(hhvm)
|
||||
add_subdirectory(system)
|
||||
|
||||
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -3,7 +3,7 @@ auto_sources(files "*.cpp" "")
|
||||
list(APPEND CXX_SOURCES ${files})
|
||||
|
||||
add_executable(hhvm ${CXX_SOURCES})
|
||||
target_link_libraries(hhvm hphp_analysis hphp_runtime_static ext_hhvm_static
|
||||
target_link_libraries(hhvm hphp_analysis hphp_runtime_static ext_hhvm_static hphp_system
|
||||
-Wl,-uregister_libevent_server)
|
||||
|
||||
add_custom_command(TARGET hhvm POST_BUILD
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
<?php
|
||||
// Copyright 2004-2013 Facebook. All Rights Reserved.
|
||||
|
||||
require_once "base.php";
|
||||
|
||||
$args = $argv;
|
||||
array_shift($args);
|
||||
$target = array_shift($args);
|
||||
|
||||
foreach ($args as $arg) {
|
||||
ReadIDLFile(realpath($arg));
|
||||
}
|
||||
|
||||
if (substr($target, -4) == '.cpp') {
|
||||
ob_start();
|
||||
printf("// @"."generated by idl/class_map.php\n");
|
||||
printf("#include \"hphp/runtime/base/base_includes.h\"\n");
|
||||
printf("#include \"hphp/runtime/ext/ext.h\"\n");
|
||||
printf("namespace HPHP {\n");
|
||||
write_constants(false);
|
||||
echo "const char *g_class_map[] = {\n";
|
||||
echo ' (const char *)ClassInfo::IsSystem, NULL, "",';
|
||||
echo ' "", NULL, NULL, NULL, ', "\n";
|
||||
foreach ($funcs as $func) {
|
||||
functionClassMap($func);
|
||||
}
|
||||
printf(" NULL,\n");
|
||||
printf(" NULL,\n");
|
||||
|
||||
printf(' "false", (const char*)4, "b:0;",'."\n");
|
||||
printf(' "true", (const char*)4, "b:1;",'."\n");
|
||||
printf(' "null", (const char*)2, "N;",'."\n");
|
||||
foreach ($constants as $constant) {
|
||||
constantClassMap($constant);
|
||||
}
|
||||
printf(' "SID", (const char *)((offsetof(GlobalVariables, k_SID) - '.
|
||||
'offsetof(GlobalVariables, stgv_Variant)) / sizeof(Variant)), '.
|
||||
"(const char *)1,\n");
|
||||
printf(' "PHP_SAPI", (const char *)((offsetof(GlobalVariables, k_PHP_SAPI) '.
|
||||
'- offsetof(GlobalVariables, stgv_Variant)) / sizeof(Variant)), '.
|
||||
"(const char *)1,\n");
|
||||
printf(" NULL, // End of constants\n");
|
||||
printf(" NULL,\n");
|
||||
|
||||
foreach ($classes as $cls) {
|
||||
classClassMap($cls);
|
||||
}
|
||||
printf(" NULL,\n");
|
||||
printf(" NULL\n");
|
||||
printf("};\n");
|
||||
printf("}\n");
|
||||
file_put_contents($target, ob_get_clean());
|
||||
} else {
|
||||
ob_start();
|
||||
printf("#ifndef _H_SYSTEM_CONSTANTS\n");
|
||||
printf("#define _H_SYSTEM_CONSTANTS\n");
|
||||
printf("// @"."generated by idl/class_map.php\n");
|
||||
printf("namespace HPHP {\n");
|
||||
printf("class StaticString;\n");
|
||||
printf("class Variant;\n");
|
||||
write_constants(true);
|
||||
printf("}\n");
|
||||
printf("#endif\n");
|
||||
file_put_contents($target, ob_get_clean());
|
||||
}
|
||||
return true;
|
||||
|
||||
function functionClassMap($func, $cls = null) {
|
||||
if (!array_key_exists('flags', $func)) {
|
||||
var_dump($func);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$attribute = (($func['flags'] &
|
||||
(IsProtected|IsPrivate|IsPublic|IsAbstract|IsStatic|IsFinal|
|
||||
AllowIntercept|NoProfile|ContextSensitive|HipHopSpecific|
|
||||
VariableArguments|RefVariableArguments|MixedVariableArguments|
|
||||
HasDocComment|NeedsActRec|FunctionIsFoldable|NoInjection|
|
||||
NoEffect|HasOptFunction)) |
|
||||
IsSystem | IsNothing);
|
||||
if ($attribute & RefVariableArguments) {
|
||||
$attribute |= VariableArguments;
|
||||
}
|
||||
if ($attribute & MixedVariableArguments) {
|
||||
$attribute |= RefVariableArguments | VariableArguments;
|
||||
}
|
||||
if ($cls === null) {
|
||||
$attribute |= IsPublic;
|
||||
} else if (!($attribute & (IsProtected|IsPrivate|IsPublic))) {
|
||||
$attribute |= IsPublic;
|
||||
}
|
||||
|
||||
if (isset($func['ref'])) $attribute |= IsReference;
|
||||
printf(' (const char *)0x%04X, "%s", "", (const char*)0, '.
|
||||
"(const char*)0,\n",
|
||||
$attribute, $func['name'], "", 0, 0);
|
||||
|
||||
if (!empty($func['doc'])) {
|
||||
printf(' "%s",'."\n", escape_cpp($func['doc']));
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
printDataType($func['return']);
|
||||
foreach ($func['args'] as $arg) {
|
||||
$attr = IsNothing;
|
||||
if (isset($arg['ref'])) $attr |= IsReference;
|
||||
printf('(const char *)0x%04X, "%s", "", ',
|
||||
$attr, $arg['name']);
|
||||
printDataType($arg['type']);
|
||||
if (array_key_exists('value', $arg)) {
|
||||
printf('"%s", (const char *)%d, "%s", (const char *)%d, ',
|
||||
escape_cpp($arg['defaultSerialized']),
|
||||
strlen($arg['defaultSerialized']),
|
||||
escape_cpp($arg['defaultText']),
|
||||
strlen($arg['defaultText']));
|
||||
} else {
|
||||
printf('"", (const char *)0, "", (const char *)0, ');
|
||||
}
|
||||
print("NULL,\n ");
|
||||
}
|
||||
print("NULL,\n");
|
||||
print(" NULL,\n");
|
||||
print(" NULL,\n");
|
||||
}
|
||||
|
||||
function classClassMap($cls) {
|
||||
$attribute = (($cls['flags'] &
|
||||
(IsAbstract|IsFinal|HasDocComment|NoDefaultSweep|
|
||||
HipHopSpecific)) |
|
||||
IsSystem | IsNothing);
|
||||
|
||||
printf(' (const char *)0x%04X, "%s", "%s", "", (const char *)0, ' .
|
||||
"(const char *)0,\n",
|
||||
$attribute,
|
||||
$cls['name'], strtolower($cls['parent'])); # revert strtolower
|
||||
|
||||
if (!empty($cls['doc'])) {
|
||||
printf(' "%s",'."\n", escape_cpp($cls['doc']));
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
foreach ($cls['ifaces'] as $iface) {
|
||||
printf('"%s", ', strtolower($iface));
|
||||
}
|
||||
printf("NULL,\n");
|
||||
|
||||
foreach ($cls['methods'] as $m) {
|
||||
functionClassMap($m, $cls);
|
||||
}
|
||||
printf(" NULL,\n");
|
||||
|
||||
foreach ($cls['properties'] as $p) {
|
||||
$att = $p['flags'] & (IsProtected|IsPrivate|IsPublic|IsStatic);
|
||||
$att |= IsNothing;
|
||||
if (!($att & (IsProtected|IsPrivate|IsPublic))) $att |= IsPublic;
|
||||
printf(" (const char *)0x%04X, \"%s\",\n", $att, $p['name']);
|
||||
printDataType($p['type']);
|
||||
}
|
||||
printf(" NULL,\n");
|
||||
|
||||
foreach ($cls['consts'] as $k) {
|
||||
constantClassMap($k, $cls['name']);
|
||||
}
|
||||
printf(" NULL,\n");
|
||||
|
||||
// no attributes
|
||||
printf(" NULL,\n");
|
||||
}
|
||||
|
||||
function constantClassMap($constant, $cls = null) {
|
||||
printf(' "%s", ', escape_cpp($constant['name']));
|
||||
if (array_key_exists('value', $constant)) {
|
||||
$v = serialize($constant['value']);
|
||||
printf('(const char*)%d, "%s",'."\n",
|
||||
strlen($v), escape_cpp($v));
|
||||
} else {
|
||||
switch ($constant['name']) {
|
||||
case 'STDOUT':
|
||||
case 'STDERR':
|
||||
case 'STDIN':
|
||||
printf("(const char *)&BuiltinFiles::Get%s, nullptr,\n",
|
||||
$constant['name']);
|
||||
return;
|
||||
}
|
||||
if ($cls !== null) {
|
||||
printf('(const char*)&q_%s$$%s, ',
|
||||
$cls, $constant['name']);
|
||||
printDataType($constant['type'], 2);
|
||||
} else {
|
||||
printf("(const char *)&k_%s, ",
|
||||
$constant['name']);
|
||||
printDataType($constant['type'], 2);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
function printDataType($t, $off = 0) {
|
||||
switch (typename($t)) {
|
||||
case 'null':
|
||||
case 'void': $s = 'KindOfNull'; $n = 8; break;
|
||||
case 'bool': $s = 'KindOfBoolean'; $n = 9; break;
|
||||
case 'int':
|
||||
case 'int64_t':$s = 'KindOfInt64'; $n = 10; break;
|
||||
case 'double': $s = 'KindOfDouble'; $n = 11; break;
|
||||
case 'String': $s = 'KindOfString'; $n = 20; break;
|
||||
case 'Array': $s = 'KindOfArray'; $n = 32; break;
|
||||
case 'Object': $s = 'KindOfObject'; $n = 64; break;
|
||||
default:
|
||||
if (is_string($t)) {
|
||||
$s = 'KindOfObject'; $n = 64;
|
||||
break;
|
||||
}
|
||||
$s = 'KindOfUnknown: $t: ' . typename($t); $n = -1;
|
||||
break;
|
||||
}
|
||||
printf('(const char *)0x%x /* %s */, ', ($n + $off) & 0xffffffff, $s);
|
||||
}
|
||||
|
||||
function write_constants($extern) {
|
||||
global $constants;
|
||||
foreach ($constants as $constant) {
|
||||
if (array_key_exists('value', $constant)) {
|
||||
$v = $constant['value'];
|
||||
if (is_bool($v)) {
|
||||
$type = 'bool';
|
||||
} else if (is_int($v)) {
|
||||
$type = 'int64_t';
|
||||
} else if (is_double($v)) {
|
||||
$type = 'double';
|
||||
} else if (is_string($v)) {
|
||||
$type = 'StaticString';
|
||||
} else if (is_null($v)) {
|
||||
$type = 'Variant';
|
||||
} else {
|
||||
throw new Exception("bad value for constant '$constant'");
|
||||
}
|
||||
if ($extern) {
|
||||
printf("extern const %s k_%s;\n",
|
||||
$type, $constant['name']);
|
||||
} else if (is_string($v)) {
|
||||
printf("extern const StaticString k_%s(%s,%d);\n",
|
||||
$constant['name'],
|
||||
php_escape_val($v), strlen($v));
|
||||
} else {
|
||||
printf("const %s k_%s = %s;\n",
|
||||
$type, $constant['name'], php_escape_val($v));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -545,7 +545,7 @@ ClassInfo::MethodInfo *ClassInfo::MethodInfo::getDeclared() {
|
||||
ClassInfo::MethodInfo::MethodInfo(const char **&p) {
|
||||
attribute = (Attribute)(int64_t)(*p++);
|
||||
name = makeStaticString(*p++);
|
||||
docComment = 0;
|
||||
docComment = "";
|
||||
if (attribute & ClassInfo::IsRedeclared) {
|
||||
volatile_redec_offset = (int)(int64_t)(*p++);
|
||||
while (*p) {
|
||||
@@ -632,6 +632,8 @@ ClassInfoUnique::ClassInfoUnique(const char **&p) {
|
||||
|
||||
if (m_attribute & HasDocComment) {
|
||||
m_docComment = *p++;
|
||||
} else {
|
||||
m_docComment = "";
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
@@ -822,3 +824,4 @@ ClassInfo::MethodInfo::~MethodInfo() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "hphp/runtime/ext/ext_reflection.h"
|
||||
#include "hphp/runtime/ext/ext_closure.h"
|
||||
#include "hphp/runtime/ext/ext_misc.h"
|
||||
#include "hphp/runtime/base/externals.h"
|
||||
#include "hphp/runtime/base/class_info.h"
|
||||
#include "hphp/runtime/base/runtime_option.h"
|
||||
@@ -227,6 +228,54 @@ static void set_static_prop_info(Array &ret, const Class::SProp* prop) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool resolveConstant(const char *p, int64_t len, Variant &cns) {
|
||||
// ltrim
|
||||
while (len && (*p == ' ')) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
// rtrim
|
||||
while (len && (p[len-1] == ' ')) {
|
||||
len--;
|
||||
}
|
||||
|
||||
String cname(p, len, CopyString);
|
||||
|
||||
if (!f_defined(cname)) {
|
||||
cns = uninit_null();
|
||||
return false;
|
||||
}
|
||||
|
||||
cns = f_constant(cname);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool resolveDefaultParameterConstant(const char *value,
|
||||
int64_t valueLen,
|
||||
Variant &cns) {
|
||||
const char *p = value;
|
||||
const char *e = value + valueLen;
|
||||
const char *s;
|
||||
bool isLval = false;
|
||||
int64_t lval = 0;
|
||||
|
||||
while ((s = strchr(p, '|'))) {
|
||||
isLval = true;
|
||||
if (!resolveConstant(p, s - p, cns)) {
|
||||
return false;
|
||||
}
|
||||
lval |= cns.toInt64();
|
||||
p = s + 1;
|
||||
}
|
||||
if (!resolveConstant(p, e - p, cns)) {
|
||||
return false;
|
||||
}
|
||||
if (isLval) {
|
||||
cns = cns.toInt64() | lval;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_function_info(Array &ret, const ClassInfo::MethodInfo *info,
|
||||
const String *classname) {
|
||||
// return type
|
||||
@@ -263,23 +312,38 @@ static void set_function_info(Array &ret, const ClassInfo::MethodInfo *info,
|
||||
param.set(s_class, VarNR(*classname));
|
||||
}
|
||||
const char *defText = p->valueText;
|
||||
if (defText == nullptr) defText = "";
|
||||
int64_t defTextLen = p->valueTextLen;
|
||||
if (defText == nullptr) {
|
||||
defText = "";
|
||||
defTextLen = 0;
|
||||
}
|
||||
if (!p->type || !*p->type || !strcasecmp("null", defText)) {
|
||||
param.set(s_nullable, true_varNR);
|
||||
}
|
||||
if (p->value && *p->value) {
|
||||
if (*p->value == '\x01') {
|
||||
const char *sep = strchr(defText, ':');
|
||||
Object v(SystemLib::AllocStdClassObject());
|
||||
if (sep && sep[1] == ':') {
|
||||
String cls = String(defText, sep - defText, CopyString);
|
||||
String con = String(sep + 2, CopyString);
|
||||
v.o_set(s_class, cls);
|
||||
v.o_set(s_name, con);
|
||||
Variant v;
|
||||
if ((defTextLen > 2) &&
|
||||
!strcmp(defText + defTextLen - 2, "()")) {
|
||||
const char *sep = strchr(defText, ':');
|
||||
v = SystemLib::AllocStdClassObject();
|
||||
if (sep && sep[1] == ':') {
|
||||
String cls = String(defText, sep - defText, CopyString);
|
||||
String con = String(sep + 2, CopyString);
|
||||
v.o_set(s_class, cls);
|
||||
v.o_set(s_name, con);
|
||||
} else {
|
||||
v.o_set(s_name, String(defText, defTextLen, CopyString));
|
||||
}
|
||||
param.set(s_default, v);
|
||||
} else if (resolveDefaultParameterConstant(defText, defTextLen, v)) {
|
||||
param.set(s_default, v);
|
||||
} else {
|
||||
v.o_set(s_msg, String("unable to eval ") + defText);
|
||||
v = SystemLib::AllocStdClassObject();
|
||||
v.o_set(s_msg, String("Unknown unserializable default value: ")
|
||||
+ defText);
|
||||
param.set(s_default, v);
|
||||
}
|
||||
param.set(s_default, v);
|
||||
} else {
|
||||
param.set(s_default, unserialize_from_string(p->value));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
class_map.cpp
|
||||
constants.h
|
||||
@@ -0,0 +1,21 @@
|
||||
auto_sources(IDL_SRCS "*.idl.json" "RECURSE" "${HPHP_HOME}/hphp/idl")
|
||||
string(REPLACE ";" " " IDL_SRCS_STR "${IDL_SRCS}")
|
||||
|
||||
set(CONSTDEF "${CMAKE_CURRENT_SOURCE_DIR}/globals/constdef.json")
|
||||
|
||||
add_custom_command(OUTPUT "class_map.cpp" "constants.h"
|
||||
DEPENDS ${CONSTDEF} ${IDL_SRCS} gen-class-map
|
||||
COMMAND "${HPHP_HOME}/hphp/tools/gen-ext-hhvm/gen-class-map.sh"
|
||||
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/class_map.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/constants.h"
|
||||
${CONSTDEF} ${IDL_SRCS_STR}
|
||||
COMMENT "Generating class_map.cpp and constants.h")
|
||||
|
||||
set(CXX_SOURCES "class_map.cpp" "lib/systemlib.cpp")
|
||||
|
||||
add_library(hphp_system STATIC ${CXX_SOURCES})
|
||||
|
||||
# Needed to force system/constants.h to generate prior to files which need it
|
||||
add_dependencies(hphp_runtime_static hphp_system)
|
||||
add_dependencies(hphp_analysis hphp_system)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
PROJECT_ROOT = ../..
|
||||
|
||||
include $(PROJECT_ROOT)/src/dirs.mk
|
||||
|
||||
PHP_FILES = $(wildcard classes/*.php) $(wildcard globals/*.php)
|
||||
|
||||
PHP := $(wildcard /usr/local/hphpi/bin/hhvm)
|
||||
PHP := $(if $(PHP),$(PHP) -v Preg.ErrorLog=false,php)
|
||||
all:
|
||||
$(HPHP) --opts=none -t cpp -f sys --input-dir . -i $(PHP_FILES) -o gen 1>/dev/null
|
||||
$(V)$(PHP) $(PROJECT_ROOT)/bin/license.php
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1,6 +1,28 @@
|
||||
{
|
||||
"preamble": "",
|
||||
"consts": [
|
||||
{
|
||||
"name": "true",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "false",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"name": "null",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"name": "SID",
|
||||
"type": "String",
|
||||
"desc": "Dynamic constant: session_id()"
|
||||
},
|
||||
{
|
||||
"name": "PHP_SAPI",
|
||||
"type": "String",
|
||||
"desc": "Dynamic constant: php_sapi_name()"
|
||||
},
|
||||
{
|
||||
"name": "ABDAY_1",
|
||||
"value": 131072
|
||||
|
||||
@@ -12,5 +12,5 @@ list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/process_init.cpp")
|
||||
list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/global_variables.cpp")
|
||||
|
||||
add_executable(test ${CXX_SOURCES})
|
||||
target_link_libraries(test hphp_analysis hphp_runtime_static ext_hhvm_static
|
||||
target_link_libraries(test hphp_analysis hphp_runtime_static ext_hhvm_static hphp_system
|
||||
-Wl,-uregister_libevent_server)
|
||||
|
||||
@@ -15,15 +15,14 @@ function info1($c) {
|
||||
$c->processCmd('@', null);
|
||||
$o = $c->processCmd('info', array('array_key_exists'));
|
||||
VS(trim($o['text']), '/**
|
||||
* ( excerpt from http://php.net/manual/en/function.array-key-exists.php )
|
||||
* ( excerpt from http://php.net/manual/en/function.array_key_exists.php )
|
||||
* array_key_exists() returns TRUE if the given key is set in the array.'.
|
||||
' key can be any value possible for an array index.
|
||||
*
|
||||
* array_key_exists() returns TRUE if the given key is set in the array.
|
||||
* key can be any value possible for an array index.
|
||||
* @key mixed Value to check.
|
||||
* @search mixed An array with keys to check.
|
||||
*
|
||||
* @key mixed Value to check.
|
||||
* @search mixed An array with keys to check.
|
||||
*
|
||||
* @return bool Returns TRUE on success or FALSE on failure.
|
||||
* @return bool Returns TRUE on success or FALSE on failure.
|
||||
*/
|
||||
function array_key_exists($key, $search);');
|
||||
$o = $c->processCmd('info', array('stdClass'));
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
echo "--SQLite3::open--\n";
|
||||
$ro = new ReflectionClass('SQLite3');
|
||||
$mo = $ro->getMethod('open');
|
||||
$params = $mo->getParameters();
|
||||
var_dump($params[1]->getDefaultValue());
|
||||
var_dump(str_replace(' ', '', $params[1]->getDefaultValueText()));
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
--SQLite3::open--
|
||||
int(6)
|
||||
string(42) "SQLITE3_OPEN_READWRITE|SQLITE3_OPEN_CREATE"
|
||||
@@ -1,3 +1,4 @@
|
||||
Makefile
|
||||
gen-ext-hhvm
|
||||
gen-infotabs
|
||||
gen-class-map
|
||||
|
||||
@@ -3,3 +3,6 @@ target_link_libraries(gen-ext-hhvm folly ${LIBGLOG_LIBRARY} double-conversion ${
|
||||
|
||||
add_executable(gen-infotabs "gen-infotabs.cpp" "idl.cpp")
|
||||
target_link_libraries(gen-infotabs folly ${LIBGLOG_LIBRARY} double-conversion ${LIBPTHREAD_LIBRARIES} ${DL_LIB})
|
||||
|
||||
add_executable(gen-class-map "gen-class-map.cpp" "idl.cpp")
|
||||
target_link_libraries(gen-class-map folly ${LIBGLOG_LIBRARY} double-conversion ${LIBPTHREAD_LIBRARIES} ${DL_LIB})
|
||||
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "folly/FBString.h"
|
||||
#include "folly/FBVector.h"
|
||||
|
||||
#include "hphp/tools/gen-ext-hhvm/idl.h"
|
||||
|
||||
using folly::fbstring;
|
||||
using folly::fbvector;
|
||||
using namespace HPHP::IDL;
|
||||
using namespace HPHP;
|
||||
|
||||
#define VISIBILITY_MASK (IsPublic|IsProtected|IsPrivate)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
static inline fbstring castLong(unsigned long lval, bool hex = false) {
|
||||
if (hex) {
|
||||
char buffer[10];
|
||||
snprintf(buffer, sizeof(buffer), "%lx", lval & 0xffffffff);
|
||||
return folly::to<fbstring>("(const char *)0x", buffer);
|
||||
}
|
||||
return folly::to<fbstring>("(const char*)", lval);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Generated doc comments
|
||||
|
||||
static fbstring formatDocComment(const fbstring& comment) {
|
||||
const char *p = comment.c_str();
|
||||
const char *s;
|
||||
const char *e = p + comment.size();
|
||||
fbstring ret("/**\n");
|
||||
while ((s = strchr(p, '\n'))) {
|
||||
ret += " *";
|
||||
if ((s - p) > 1) {
|
||||
ret += " " + fbstring(p, (s - p));
|
||||
}
|
||||
ret += "\n";
|
||||
p = s + 1;
|
||||
}
|
||||
if (p < e) {
|
||||
ret += " * " + fbstring(p) + "\n";
|
||||
}
|
||||
return ret + " */";
|
||||
}
|
||||
|
||||
static fbstring genDocCommentPreamble(const fbstring& name,
|
||||
const fbstring& desc,
|
||||
long flags,
|
||||
const fbstring& classname) {
|
||||
fbstring ret;
|
||||
|
||||
if (flags & HipHopSpecific) {
|
||||
ret = "( HipHop specific )";
|
||||
} else {
|
||||
ret = "( excerpt from http://php.net/manual/en/";
|
||||
if (classname.size()) {
|
||||
ret += classname + ".";
|
||||
} else {
|
||||
ret += "function.";
|
||||
}
|
||||
ret += name + ".php )";
|
||||
}
|
||||
|
||||
if (desc.size()) {
|
||||
ret += "\n" + desc;
|
||||
}
|
||||
return ret + "\n\n";
|
||||
}
|
||||
|
||||
static fbstring genDocComment(const PhpFunc& func,
|
||||
const fbstring& classname) {
|
||||
fbstring ret(genDocCommentPreamble(func.name(), func.getDesc(),
|
||||
func.flags(), classname));
|
||||
|
||||
for (auto ¶m : func.params()) {
|
||||
ret += "@" + param.name() + " " + param.getPhpType() + " ";
|
||||
if (param.isRef()) {
|
||||
ret += "(output) ";
|
||||
}
|
||||
ret += param.getDesc() + "\n";
|
||||
}
|
||||
|
||||
if (func.numParams() > 0) {
|
||||
ret += "\n";
|
||||
}
|
||||
|
||||
auto rko = func.returnKindOf();
|
||||
if ((rko != KindOfNull) && (rko != KindOfInvalid)) {
|
||||
ret += "@return " + func.returnPhpType() + " ";
|
||||
if (func.isReturnRef()) {
|
||||
ret += "(output) ";
|
||||
}
|
||||
ret += func.returnDesc() + "\n";
|
||||
}
|
||||
|
||||
return formatDocComment(ret);
|
||||
}
|
||||
|
||||
static fbstring genDocComment(const PhpClass& cls) {
|
||||
return formatDocComment(
|
||||
genDocCommentPreamble(cls.name(), cls.getDesc(), cls.flags(), "")
|
||||
);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// System constants
|
||||
|
||||
static void declareConstants(std::ostream &out,
|
||||
const fbvector<PhpConst>& consts,
|
||||
bool extrn) {
|
||||
for (auto c : consts) {
|
||||
if (!c.hasValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (extrn) {
|
||||
out << "extern const " << c.getCppType() << " " << c.varname() << ";\n";
|
||||
} else if (c.kindOf() == KindOfString) {
|
||||
fbstring val = c.value();
|
||||
out << "extern const StaticString " << c.varname()
|
||||
<< "(\"" << escapeCpp(val) << "\"," << val.size() << ");\n";
|
||||
} else {
|
||||
out << "const " << c.getCppType() << " " << c.varname()
|
||||
<< " = " << escapeCpp(c.value()) << ";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int outputConstants(const char *outputfn,
|
||||
const fbvector<PhpConst>& consts) {
|
||||
std::ofstream out(outputfn);
|
||||
|
||||
out << "// @" "generated by gen-class-map.cpp\n"
|
||||
<< "#ifndef _H_SYSTEM_CONSTANTS\n"
|
||||
<< "#define _H_SYSTEM_CONSTANTS\n"
|
||||
<< "namespace HPHP {\n"
|
||||
<< "class StaticString;\n"
|
||||
<< "class Variant;\n";
|
||||
declareConstants(out, consts, true);
|
||||
out << "} // namespace HPHP\n"
|
||||
<< "#endif // _H_SYSTEM_CONSTANTS\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Class Map
|
||||
|
||||
#define FUNC_FLAG_MASK (IsProtected|IsPrivate|IsPublic|\
|
||||
IsAbstract|IsStatic|IsFinal|HasDocComment|\
|
||||
AllowIntercept|NoProfile|ContextSensitive|\
|
||||
HipHopSpecific|VariableArguments|\
|
||||
RefVariableArguments|MixedVariableArguments|\
|
||||
NeedsActRec|FunctionIsFoldable|\
|
||||
NoInjection|NoEffect|HasOptFunction)
|
||||
|
||||
static void writeFunction(std::ostream& out, const PhpFunc& func) {
|
||||
auto flags = (func.flags() & FUNC_FLAG_MASK) | IsSystem | IsNothing;
|
||||
|
||||
if (flags & RefVariableArguments) {
|
||||
flags |= VariableArguments;
|
||||
}
|
||||
if (flags & MixedVariableArguments) {
|
||||
flags |= RefVariableArguments | VariableArguments;
|
||||
}
|
||||
if (!func.isMethod() || !(flags & VISIBILITY_MASK)) {
|
||||
flags |= IsPublic;
|
||||
}
|
||||
if (func.isReturnRef()) {
|
||||
flags |= IsReference;
|
||||
}
|
||||
|
||||
out << " " << castLong(flags, true) << ", \"" << func.name() << "\", "
|
||||
<< "\"\", "
|
||||
<< castLong(0) << ", "
|
||||
<< castLong(0) << ",\n";
|
||||
|
||||
if (flags & HasDocComment) {
|
||||
out << " \""
|
||||
<< escapeCpp(genDocComment(func, func.className()))
|
||||
<< "\",\n";
|
||||
}
|
||||
|
||||
DataType rko = func.returnKindOf();
|
||||
if (rko == KindOfAny) {
|
||||
// ClassInfo::MethodInfo expects this for Any/Variant
|
||||
// TODO: Fix that broken assumption
|
||||
rko = KindOfInvalid;
|
||||
}
|
||||
out << " " << castLong(rko, true) << ",\n";
|
||||
for (auto &p : func.params()) {
|
||||
long attr = IsNothing;
|
||||
DataType ko = p.kindOf();
|
||||
if (p.isRef()) {
|
||||
// We don't declare param type as KindOfRef
|
||||
// as then the caller will try to cast it as such
|
||||
attr |= IsReference;
|
||||
ko = KindOfAny;
|
||||
}
|
||||
if (ko == KindOfAny) {
|
||||
// TODO: See above
|
||||
ko = KindOfInvalid;
|
||||
}
|
||||
out << " "
|
||||
<< castLong(attr, true) << ", "
|
||||
<< "\"" << escapeCpp(p.name()) << "\", \"\", "
|
||||
<< castLong(ko, true) << ",\n";
|
||||
auto ser = p.getDefaultSerialized();
|
||||
auto val = p.getDefaultPhp();
|
||||
out << " "
|
||||
<< "\"" << escapeCpp(ser) << "\", " << castLong(ser.size()) << ", "
|
||||
<< "\"" << escapeCpp(val) << "\", " << castLong(val.size()) << ", "
|
||||
<< "NULL,\n";
|
||||
}
|
||||
out << " NULL,\n"
|
||||
<< " NULL,\n"
|
||||
<< " NULL,\n";
|
||||
}
|
||||
|
||||
static void writeConstant(std::ostream& out, const PhpConst& cns) {
|
||||
auto name = cns.name();
|
||||
out << " \"" << escapeCpp(name) << "\", ";
|
||||
if (cns.hasValue()) {
|
||||
auto ser = cns.serialize();
|
||||
out << castLong(ser.size())
|
||||
<< ", \"" << escapeCpp(ser) << "\",\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (cns.isSystem()) {
|
||||
// Special "magic" constants
|
||||
if ((name == "SID") || (name == "PHP_SAPI")) {
|
||||
out << "(const char *)((offsetof(GlobalVariables, k_" << name << ") - "
|
||||
<< "offsetof(GlobalVariables, stgv_Variant)) / sizeof(Variant)), "
|
||||
<< castLong(1) << ",\n";
|
||||
return;
|
||||
}
|
||||
if ((name == "STDIN") || (name == "STDOUT") || (name == "STDERR")) {
|
||||
out << "(const char *)&BuiltinFiles::Get" << name << ", NULL,\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
out << "(const char *)&" << cns.varname() << ", "
|
||||
<< castLong((int)cns.kindOf() + 2) << ",\n";
|
||||
}
|
||||
|
||||
#define CLASS_FLAG_MASK (IsAbstract|IsFinal|NoDefaultSweep|\
|
||||
HipHopSpecific|HasDocComment)
|
||||
#define PROP_FLAG_MASK (IsProtected|IsPrivate|IsPublic|IsStatic)
|
||||
|
||||
static void writeClass(std::ostream& out, const PhpClass& cls) {
|
||||
auto flags = (cls.flags() & CLASS_FLAG_MASK) | IsSystem | IsNothing;
|
||||
|
||||
out << " " << castLong(flags, true) << ", "
|
||||
<< "\"" << escapeCpp(cls.name()) << "\", "
|
||||
<< "\"" << escapeCpp(strtolower(cls.parent())) << "\", "
|
||||
<< "\"\", "
|
||||
<< castLong(0) << ", "
|
||||
<< castLong(0) << ",\n";
|
||||
|
||||
if (flags & HasDocComment) {
|
||||
out << " \"" << escapeCpp(genDocComment(cls)) << "\",\n";
|
||||
}
|
||||
|
||||
out << " ";
|
||||
for (auto &iface : cls.ifaces()) {
|
||||
out << "\"" << escapeCpp(strtolower(iface)) << "\", ";
|
||||
}
|
||||
out << "NULL,\n";
|
||||
|
||||
for (auto &method : cls.methods()) {
|
||||
writeFunction(out, method);
|
||||
}
|
||||
out << " NULL,\n";
|
||||
|
||||
for (auto &prop : cls.properties()) {
|
||||
auto propflag = (prop.flags() & PROP_FLAG_MASK) | IsNothing;
|
||||
if (!(propflag & VISIBILITY_MASK)) {
|
||||
propflag |= IsPublic;
|
||||
}
|
||||
out << " " << castLong(propflag, true) << ", "
|
||||
<< "\"" << escapeCpp(prop.name()) << "\", "
|
||||
<< castLong((int)prop.kindOf(), true) << ",\n";
|
||||
}
|
||||
out << " NULL,\n";
|
||||
|
||||
for (auto &cns : cls.constants()) {
|
||||
writeConstant(out, cns);
|
||||
}
|
||||
out << " NULL,\n";
|
||||
|
||||
out << " NULL,\n"; // no attributes
|
||||
}
|
||||
|
||||
static int outputClassMap(const char *outputfn, const char *classmap_name,
|
||||
const fbvector<PhpClass>& classes,
|
||||
const fbvector<PhpFunc>& funcs,
|
||||
const fbvector<PhpConst>& consts) {
|
||||
std::ofstream out(outputfn);
|
||||
|
||||
out << "// @" "generated by gen-class-map.cpp\n"
|
||||
<< "#include \"hphp/runtime/base/base_includes.h\"\n"
|
||||
<< "#include \"hphp/runtime/ext/ext.h\"\n"
|
||||
<< "namespace HPHP {\n";
|
||||
declareConstants(out, consts, false);
|
||||
out << "const char *" << classmap_name << "[] = {\n"
|
||||
<< " (const char *)ClassInfo::IsSystem, NULL, "
|
||||
<< "\"\", \"\", NULL, NULL, NULL,\n";
|
||||
for (auto &f : funcs) {
|
||||
writeFunction(out, f);
|
||||
}
|
||||
out << " NULL,\n" // End of functions
|
||||
<< " NULL,\n"; // End of system "properties"
|
||||
for (auto &c : consts) {
|
||||
writeConstant(out, c);
|
||||
}
|
||||
out << " NULL,\n" // End of constants
|
||||
<< " NULL,\n"; // End of system "attributes"
|
||||
for (auto &c : classes) {
|
||||
writeClass(out, c);
|
||||
}
|
||||
out << " NULL,\n" // End of classes
|
||||
<< " NULL,\n" // End of classmap
|
||||
<< "};\n"
|
||||
<< "} // namespace HPHP\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 4) {
|
||||
std::cout << "Usage: " << argv[0]
|
||||
<< " [constants | classmap(:g_class_map)] "
|
||||
<< "<outputfile> <*.idl.json>...\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
fbvector<PhpFunc> funcs;
|
||||
fbvector<PhpClass> classes;
|
||||
fbvector<PhpConst> consts;
|
||||
|
||||
for (auto i = 3; i < argc; ++i) {
|
||||
try {
|
||||
parseIDL(argv[i], funcs, classes, consts);
|
||||
} catch (const std::exception& exc) {
|
||||
std::cerr << argv[i] << ": " << exc.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// System-wide class map e.g.: hphp/system/class_map.cpp
|
||||
if (!strcmp(argv[1], "classmap")) {
|
||||
return outputClassMap(argv[2], "g_class_map",
|
||||
classes, funcs, consts);
|
||||
}
|
||||
|
||||
// Extension-local class map
|
||||
if (!strncmp(argv[1], "classmap:", sizeof("classmap:") - 1)) {
|
||||
return outputClassMap(argv[2], argv[1] + (sizeof("classmap:") - 1),
|
||||
classes, funcs, consts);
|
||||
}
|
||||
|
||||
// Externs for system constants from constdef.json
|
||||
if (!strcmp(argv[1], "constants")) {
|
||||
return outputConstants(argv[2], consts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Arquivo executável
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
# $1 class_map cpp file to build
|
||||
# $2 constants.h file to build
|
||||
# $3 globals/constdef.json
|
||||
# $4- Additional IDL files to parse for class_map
|
||||
|
||||
CLASSMAP=$1
|
||||
CONSTANTS=$2
|
||||
CONSTDEF=$3
|
||||
shift; shift; shift;
|
||||
|
||||
$HPHP_HOME/hphp/tools/gen-ext-hhvm/gen-class-map \
|
||||
constants $CONSTANTS $CONSTDEF
|
||||
|
||||
$HPHP_HOME/hphp/tools/gen-ext-hhvm/gen-class-map \
|
||||
classmap $CLASSMAP $CONSTDEF $@
|
||||
|
||||
@@ -52,6 +52,7 @@ static const std::unordered_map<fbstring, DataType> g_kindOfMap =
|
||||
static const std::unordered_map<int, fbstring> g_typeMap =
|
||||
{
|
||||
{(int)KindOfInvalid, "void"},
|
||||
{(int)KindOfNull, "HPHP::Variant"},
|
||||
{(int)KindOfBoolean, "bool"},
|
||||
{(int)KindOfInt64, "long"},
|
||||
{(int)KindOfDouble, "double"},
|
||||
@@ -61,6 +62,19 @@ static const std::unordered_map<int, fbstring> g_typeMap =
|
||||
{(int)KindOfAny, "HPHP::Variant"},
|
||||
};
|
||||
|
||||
static const std::unordered_map<int, fbstring> g_phpTypeMap =
|
||||
{
|
||||
{(int)KindOfInvalid, "void"},
|
||||
{(int)KindOfNull, "void"},
|
||||
{(int)KindOfBoolean, "bool"},
|
||||
{(int)KindOfInt64, "long"},
|
||||
{(int)KindOfDouble, "double"},
|
||||
{(int)KindOfString, "String"},
|
||||
{(int)KindOfArray, "Array"},
|
||||
{(int)KindOfObject, "Object"},
|
||||
{(int)KindOfAny, "mixed"},
|
||||
};
|
||||
|
||||
static const std::unordered_map<fbstring, FuncFlags> g_flagsMap =
|
||||
{
|
||||
{"IsAbstract", IsAbstract},
|
||||
@@ -99,9 +113,11 @@ bool isKindOfIndirect(DataType kindof) {
|
||||
return (kindof != KindOfBoolean) &&
|
||||
(kindof != KindOfInt64) &&
|
||||
(kindof != KindOfDouble) &&
|
||||
(kindof != KindOfInvalid);
|
||||
(kindof != KindOfInvalid) &&
|
||||
(kindof != KindOfNull);
|
||||
}
|
||||
|
||||
// Parse type from a descriptive string, e.g. "int", "bool", etc...
|
||||
static DataType kindOfFromDynamic(const folly::dynamic& t) {
|
||||
if (!t.isString()) {
|
||||
return KindOfInvalid;
|
||||
@@ -114,6 +130,40 @@ static DataType kindOfFromDynamic(const folly::dynamic& t) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// Infer type from an actual value, e.g. 123, "foo", null, true, etc...
|
||||
static DataType kindOfFromValue(const folly::dynamic& v) {
|
||||
if (v.isNull()) {
|
||||
return KindOfNull;
|
||||
}
|
||||
if (v.isBool()) {
|
||||
return KindOfBoolean;
|
||||
}
|
||||
if (v.isInt()) {
|
||||
return KindOfInt64;
|
||||
}
|
||||
if (v.isDouble()) {
|
||||
return KindOfDouble;
|
||||
}
|
||||
if (v.isString()) {
|
||||
return KindOfString;
|
||||
}
|
||||
if (v.isArray()) {
|
||||
return KindOfArray;
|
||||
}
|
||||
if (v.isObject()) {
|
||||
return KindOfObject;
|
||||
}
|
||||
return KindOfInvalid;
|
||||
}
|
||||
|
||||
static fbstring phpTypeFromDataType(DataType dt) {
|
||||
auto it = g_phpTypeMap.find((int)dt);
|
||||
if (it == g_phpTypeMap.end()) {
|
||||
return "mixed";
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
static fbstring typeString(const folly::dynamic& typeNode, bool isReturnType) {
|
||||
if (typeNode == "Int32") {
|
||||
return "int";
|
||||
@@ -150,13 +200,289 @@ static unsigned long parseFlags(const folly::dynamic &flags) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const std::unordered_map<fbstring,fbstring> g_serializedDefaults = {
|
||||
{"true", "b:1;"},
|
||||
{"false", "b:0;"},
|
||||
{"null", "N;"},
|
||||
{"empty_array", "a:0:{}"},
|
||||
{"null_string", "N;"},
|
||||
{"null_array", "N;"},
|
||||
{"null_object", "N;"},
|
||||
{"null_variant", "N;"},
|
||||
{"INT_MAX", "i:2147483647;"}, // (1 << 31) - 1
|
||||
};
|
||||
|
||||
static const std::unordered_map<fbstring,fbstring> g_phpDefaults = {
|
||||
{"true", "true"},
|
||||
{"false", "false"},
|
||||
{"null", "null"},
|
||||
{"empty_array", "array()"},
|
||||
{"null_string", "null"},
|
||||
{"null_array", "null"},
|
||||
{"null_object", "null"},
|
||||
{"null_variant", "null"},
|
||||
{"INT_MAX", "null"},
|
||||
};
|
||||
|
||||
/**
|
||||
* From idl/base.php:get_serialized_default()
|
||||
*/
|
||||
fbstring PhpParam::getDefaultSerialized() const {
|
||||
auto valIt = m_param.find("value");
|
||||
if (valIt == m_param.items().end()) {
|
||||
return ""; // No default
|
||||
}
|
||||
auto dval = valIt->second;
|
||||
if (!dval.isString()) {
|
||||
throw std::logic_error(
|
||||
folly::format("Parameter '{0}' default value is non-string",
|
||||
m_name).str()
|
||||
);
|
||||
}
|
||||
auto val = dval.asString();
|
||||
if (!val.size()) {
|
||||
throw std::logic_error(
|
||||
folly::format("Parameter '{0}' default value malformed (empty string), "
|
||||
"specify \"\" as default value for actual empty string",
|
||||
m_name).str()
|
||||
);
|
||||
}
|
||||
|
||||
// Function calls "foo()" or "foo::bar()" to C/C++ functions/static methods,
|
||||
// a constant, or a bitmask of constants
|
||||
//
|
||||
// Used by ext_reflection to resolve the value at runtime or
|
||||
// represent the function/method call.
|
||||
if ((val.size() > 2) &&
|
||||
(!strncmp(val.c_str(), "k_", 2) ||
|
||||
!strncmp(val.c_str(), "q_", 2) ||
|
||||
!strcmp(val.c_str() + val.size() - 2, "()"))) {
|
||||
return "\x01";
|
||||
}
|
||||
|
||||
// Fixed substitutions
|
||||
auto it = g_serializedDefaults.find(val);
|
||||
if (it != g_serializedDefaults.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if (val == "RAND_MAX") {
|
||||
return folly::to<fbstring>("i:", RAND_MAX, ";");
|
||||
}
|
||||
|
||||
// Quoted string: "foo"
|
||||
if ((val.size() >= 2) && (val[0] == '"') && (val[val.size()-1] == '"')) {
|
||||
return phpSerialize(val.substr(1, val.size() - 2));
|
||||
}
|
||||
|
||||
// Integers and Floats
|
||||
if (strchr(val.c_str(), '.')) {
|
||||
// Decimal float?
|
||||
char *e = nullptr;
|
||||
double dval = strtod(val.c_str(), &e);
|
||||
if (e && !*e) {
|
||||
return folly::to<fbstring>("d:", dval, ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (val[0] == '0') {
|
||||
if ((val.size() > 1) && (val[1] == 'x')) {
|
||||
// Hex?
|
||||
char *e = nullptr;
|
||||
long lval = strtol(val.c_str() + 2, &e, 16);
|
||||
if (e && !*e) {
|
||||
return folly::to<fbstring>("i:", lval, ";");
|
||||
}
|
||||
} else {
|
||||
// Octal?
|
||||
char *e = nullptr;
|
||||
long lval = strtol(val.c_str() + 1, &e, 8);
|
||||
if (e && !*e) {
|
||||
return folly::to<fbstring>("i:", lval, ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decimal?
|
||||
char *e = nullptr;
|
||||
long lval = strtol(val.c_str(), &e, 10);
|
||||
if (e && !*e) {
|
||||
return folly::to<fbstring>("i:", lval, ";");
|
||||
}
|
||||
|
||||
throw std::logic_error(
|
||||
folly::format("'{0}' is not a valid default arg value", val).str()
|
||||
);
|
||||
}
|
||||
|
||||
static fbstring transformConstants(const fbstring val) {
|
||||
fbstring ret = val;
|
||||
int i = 0;
|
||||
int len = ret.size();
|
||||
|
||||
while (i < len) {
|
||||
while ((i < len) && (ret[i] == ' ')) i++;
|
||||
if ((len - i) < 2) break;
|
||||
|
||||
if ((ret[i+1] == '_') &&
|
||||
((ret[i] == 'k') || (ret[i] == 'q'))) {
|
||||
ret[i] = ret[i+1] = ' ';
|
||||
}
|
||||
while ((i < len) && (ret[i] != '|')) {
|
||||
if (ret[i] == '$') {
|
||||
ret[i] = ':';
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
fbstring PhpParam::getDefaultPhp() const {
|
||||
fbstring val = getDefault();
|
||||
if (!val.size()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
auto it = g_phpDefaults.find(val);
|
||||
if (it != g_phpDefaults.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if (val == "RAND_MAX") {
|
||||
return folly::to<fbstring>(RAND_MAX);
|
||||
}
|
||||
|
||||
if ((val.size() > 2) && (val[1] == '_') &&
|
||||
((val[0] == 'k') || (val[0] == 'q'))) {
|
||||
return transformConstants(val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
fbstring phpSerialize(const folly::dynamic& d) {
|
||||
if (d.isNull()) {
|
||||
return "N;";
|
||||
}
|
||||
if (d.isBool()) {
|
||||
return d.asBool() ? "b:1;" : "b:0;";
|
||||
}
|
||||
if (d.isInt()) {
|
||||
return "i:" + d.asString() + ";";
|
||||
}
|
||||
if (d.isDouble()) {
|
||||
return "d:" + d.asString() + ";";
|
||||
}
|
||||
if (d.isString()) {
|
||||
auto str = d.asString();
|
||||
return folly::to<fbstring>("s:", str.size(), ":\"", str, "\";");
|
||||
}
|
||||
if (d.isArray()) {
|
||||
fbstring ret = folly::to<fbstring>("a:", d.size(), ":{");
|
||||
int i = 0;
|
||||
for (auto &v : d) {
|
||||
ret += folly::to<fbstring>("i:", i, ";", phpSerialize(v));
|
||||
}
|
||||
return ret + "};";
|
||||
}
|
||||
if (d.isObject()) {
|
||||
fbstring ret = folly::to<fbstring>("a:", d.size(), ":{");
|
||||
int nextindex = 0;
|
||||
for (auto &k : d.keys()) {
|
||||
if (k.isNull()) {
|
||||
ret += "i:0;";
|
||||
if (nextindex <= 0) {
|
||||
nextindex = 1;
|
||||
}
|
||||
} else if (k.isInt() || k.isDouble()) {
|
||||
int i = k.asInt();
|
||||
ret += folly::to<fbstring>("i:", i, ";");
|
||||
if (nextindex <= i) {
|
||||
nextindex = i + 1;
|
||||
}
|
||||
} else if (k.isString()) {
|
||||
ret += folly::to<fbstring>("s:", k.size(), ":\"",
|
||||
escapeCpp(k.asString()), "\";");
|
||||
} else {
|
||||
/* Should never be reached, but cover it to be safe */
|
||||
ret += folly::to<fbstring>("i:", nextindex++, ";");
|
||||
}
|
||||
ret += phpSerialize(d[k]);
|
||||
}
|
||||
return ret + "};";
|
||||
}
|
||||
throw std::logic_error("Unhandled dynamic type in php serialization");
|
||||
return "N;";
|
||||
}
|
||||
|
||||
static fbstring getFollyDynamicDefaultString(const folly::dynamic& d,
|
||||
const fbstring& key,
|
||||
const fbstring& def) {
|
||||
auto it = d.find(key);
|
||||
if (it == d.items().end()) {
|
||||
return def;
|
||||
}
|
||||
auto val = it->second;
|
||||
if (val.isNull()) {
|
||||
return def;
|
||||
}
|
||||
return val.asString();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// PhpConst
|
||||
|
||||
bool PhpConst::parseType(const folly::dynamic& cns) {
|
||||
auto it = cns.find("type");
|
||||
if (it != cns.items().end()) {
|
||||
m_kindOf = kindOfFromDynamic(it->second);
|
||||
m_cppType = typeString(it->second, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PhpConst::inferType(const folly::dynamic& cns) {
|
||||
auto it = cns.find("value");
|
||||
if (it != cns.items().end()) {
|
||||
m_kindOf = kindOfFromValue(it->second);
|
||||
auto typeIt = g_typeMap.find((int)m_kindOf);
|
||||
if (typeIt != g_typeMap.end()) {
|
||||
m_cppType = typeIt->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PhpConst::PhpConst(const folly::dynamic& cns,
|
||||
fbstring cls /* = "" */) :
|
||||
m_constant(cns),
|
||||
m_name(cns["name"].asString()),
|
||||
m_className(cls) {
|
||||
if (!parseType(cns) && !inferType(cns)) {
|
||||
// Constant has neither explicit type nor implicit type from 'value'
|
||||
assert(false);
|
||||
m_kindOf = KindOfInvalid;
|
||||
m_cppType = "void";
|
||||
}
|
||||
|
||||
// Override typeString()'s selection for string values
|
||||
if (m_kindOf == KindOfString) {
|
||||
m_cppType = "HPHP::StaticString";
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// PhpParam
|
||||
|
||||
PhpParam::PhpParam(const folly::dynamic& param,
|
||||
bool isMagicMethod /*= false */) :
|
||||
m_name(param["name"].asString()),
|
||||
m_param(param) {
|
||||
m_param(param),
|
||||
m_desc(getFollyDynamicDefaultString(param, "desc", "")) {
|
||||
if (isMagicMethod) {
|
||||
m_kindOf = KindOfAny;
|
||||
m_cppType = "HPHP::Variant";
|
||||
@@ -170,6 +496,8 @@ PhpParam::PhpParam(const folly::dynamic& param,
|
||||
m_kindOf = kindOfFromDynamic(param["type"]);
|
||||
m_cppType = typeString(param["type"], false);
|
||||
}
|
||||
|
||||
m_phpType = phpTypeFromDataType(m_kindOf);
|
||||
}
|
||||
|
||||
bool PhpParam::defValueNeedsVariable() const {
|
||||
@@ -208,13 +536,28 @@ PhpFunc::PhpFunc(const folly::dynamic& d,
|
||||
m_name(d["name"].asString()),
|
||||
m_className(className),
|
||||
m_func(d),
|
||||
m_desc(getFollyDynamicDefaultString(d, "desc", "")),
|
||||
m_returnRef(d.getDefault("ref", "false") == "true"),
|
||||
m_returnKindOf(m_returnRef ? KindOfRef :
|
||||
kindOfFromDynamic(d["return"]["type"])),
|
||||
m_returnCppType(typeString(d["return"]["type"], true)),
|
||||
m_returnKindOf(KindOfNull),
|
||||
m_returnCppType("void"),
|
||||
m_returnPhpType("void"),
|
||||
m_minNumParams(0),
|
||||
m_numTypeChecks(0) {
|
||||
// Better at least have a name
|
||||
auto returnIt = d.find("return");
|
||||
if (returnIt != d.items().end()) {
|
||||
auto retNode = returnIt->second;
|
||||
auto typeIt = retNode.find("type");
|
||||
if (typeIt != retNode.items().end()) {
|
||||
auto type = typeIt->second;
|
||||
if ((type.isString()) && (type != "void") && (type != "null")) {
|
||||
m_returnKindOf = m_returnRef ? KindOfRef : kindOfFromDynamic(type);
|
||||
m_returnCppType = typeString(type, true);
|
||||
m_returnPhpType = phpTypeFromDataType(m_returnKindOf);
|
||||
}
|
||||
}
|
||||
m_returnDesc = getFollyDynamicDefaultString(retNode, "desc", "");
|
||||
}
|
||||
|
||||
auto args = d.find("args");
|
||||
if (args == d.items().end() || !args->second.isArray()) {
|
||||
throw std::logic_error(
|
||||
@@ -289,24 +632,65 @@ fbstring PhpFunc::getCppSig() const {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// PhpProp
|
||||
|
||||
PhpProp::PhpProp(const folly::dynamic& d, fbstring cls) :
|
||||
m_name(d["name"].asString()),
|
||||
m_className(cls),
|
||||
m_prop(d),
|
||||
m_flags(parseFlags(m_prop["flags"])),
|
||||
m_kindOf(kindOfFromDynamic(m_prop["type"])) {
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// PhpClass
|
||||
|
||||
PhpClass::PhpClass(const folly::dynamic &c) :
|
||||
m_class(c),
|
||||
m_name(c["name"].asString()) {
|
||||
m_name(c["name"].asString()),
|
||||
m_flags(parseFlags(m_class["flags"])),
|
||||
m_desc(getFollyDynamicDefaultString(c, "desc", "")) {
|
||||
|
||||
auto ifacesIt = m_class.find("ifaces");
|
||||
if (ifacesIt != m_class.items().end()) {
|
||||
auto ifaces = ifacesIt->second;
|
||||
if (!ifaces.isArray()) {
|
||||
throw std::logic_error(
|
||||
folly::format("Class {0}.ifaces field must be an array", m_name).str()
|
||||
);
|
||||
}
|
||||
for (auto &interface : ifaces) {
|
||||
m_ifaces.push_back(interface.asString());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& f : c["funcs"]) {
|
||||
PhpFunc func(f, m_name);
|
||||
m_methods.push_back(func);
|
||||
}
|
||||
m_flags = parseFlags(m_class["flags"]);
|
||||
|
||||
if (c.find("consts") != c.items().end()) {
|
||||
for (auto const& cns : c["consts"]) {
|
||||
PhpConst cons(cns, m_name);
|
||||
m_constants.push_back(cons);
|
||||
}
|
||||
}
|
||||
|
||||
if (c.find("properties") != c.items().end()) {
|
||||
for (auto const& prp : c["properties"]) {
|
||||
PhpProp prop(prp, m_name);
|
||||
m_properties.push_back(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseIDL(const char* idlFilePath,
|
||||
fbvector<PhpFunc>& funcVec,
|
||||
fbvector<PhpClass>& classVec) {
|
||||
fbvector<PhpClass>& classVec,
|
||||
fbvector<PhpConst>& constVec) {
|
||||
std::ostringstream jsonString;
|
||||
std::ifstream infile(idlFilePath);
|
||||
infile >> jsonString.rdbuf();
|
||||
@@ -321,6 +705,17 @@ void parseIDL(const char* idlFilePath,
|
||||
PhpClass klass(c);
|
||||
classVec.push_back(klass);
|
||||
}
|
||||
for (auto const& c : parsed["consts"]) {
|
||||
PhpConst cns(c);
|
||||
constVec.push_back(cns);
|
||||
}
|
||||
}
|
||||
|
||||
void parseIDL(const char* idlFilePath,
|
||||
fbvector<PhpFunc>& funcVec,
|
||||
fbvector<PhpClass>& classVec) {
|
||||
fbvector<PhpConst> consts; // dummy
|
||||
parseIDL(idlFilePath, funcVec, classVec, consts);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -86,11 +86,84 @@ static inline fbstring kindOfString(DataType t) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline fbstring escapeCpp(const fbstring& str) {
|
||||
std::ostringstream ssb;
|
||||
for (auto c : str) {
|
||||
switch (c) {
|
||||
case '\n': ssb << "\\n"; break;
|
||||
case '\r': ssb << "\\r"; break;
|
||||
case '\t': ssb << "\\t"; break;
|
||||
case '\a': ssb << "\\a"; break;
|
||||
case '\b': ssb << "\\b"; break;
|
||||
case '\f': ssb << "\\f"; break;
|
||||
case '\v': ssb << "\\v"; break;
|
||||
case '\0': ssb << "\\000"; break;
|
||||
case '\"': ssb << "\\\""; break;
|
||||
case '\\': ssb << "\\\\"; break;
|
||||
case '\?': ssb << "\\?"; break; // trigraphs
|
||||
default:
|
||||
if ((c >= 0x20) && (c <= 0x7f)) {
|
||||
ssb << c;
|
||||
} else {
|
||||
char buf[6];
|
||||
snprintf(buf, sizeof(buf), "\\%03o", (unsigned int)c);
|
||||
ssb << buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fbstring(ssb.str());
|
||||
}
|
||||
|
||||
static inline fbstring strtolower(const fbstring& str) {
|
||||
fbstring lcase = str;
|
||||
std::transform(str.begin(), str.end(), lcase.begin(),
|
||||
std::ptr_fun<int, int>(std::tolower));
|
||||
return lcase;
|
||||
}
|
||||
|
||||
fbstring phpSerialize(const folly::dynamic& d);
|
||||
|
||||
class PhpConst {
|
||||
public:
|
||||
explicit PhpConst(const folly::dynamic& cns, fbstring cls = "");
|
||||
|
||||
fbstring name() const { return m_name; }
|
||||
fbstring varname() const {
|
||||
return m_className.empty() ? ("k_" + m_name)
|
||||
: ("q_" + m_className + "$$" + m_name);
|
||||
}
|
||||
bool isSystem() const { return m_className.empty(); }
|
||||
fbstring getCppType() const { return m_cppType; }
|
||||
DataType kindOf() const { return m_kindOf; }
|
||||
bool hasValue() const {
|
||||
return (m_constant.find("value") != m_constant.items().end());
|
||||
}
|
||||
fbstring value() const {
|
||||
auto it = m_constant.find("value");
|
||||
assert(it != m_constant.items().end());
|
||||
auto v = it->second;
|
||||
return v.isNull() ? "uninit_null()" : v.asString();
|
||||
}
|
||||
|
||||
fbstring serialize() const { return phpSerialize(m_constant["value"]); }
|
||||
|
||||
private:
|
||||
folly::dynamic m_constant;
|
||||
fbstring m_name;
|
||||
fbstring m_className;
|
||||
fbstring m_cppType;
|
||||
DataType m_kindOf;
|
||||
|
||||
bool parseType(const folly::dynamic& cns);
|
||||
bool inferType(const folly::dynamic& cns);
|
||||
};
|
||||
|
||||
class PhpParam {
|
||||
public:
|
||||
explicit PhpParam(const folly::dynamic& param, bool isMagicMethod = false);
|
||||
|
||||
fbstring name() const { return m_name; }
|
||||
fbstring getDesc() const { return m_desc; }
|
||||
fbstring getCppType() const { return m_cppType; }
|
||||
fbstring getStrippedCppType() const {
|
||||
fbstring ret = m_cppType;
|
||||
@@ -103,6 +176,7 @@ class PhpParam {
|
||||
return ret;
|
||||
}
|
||||
DataType kindOf() const { return m_kindOf; }
|
||||
fbstring getPhpType() const { return m_phpType; }
|
||||
|
||||
bool isRef() const { return m_param.getDefault("ref", false).asBool(); }
|
||||
|
||||
@@ -112,6 +186,8 @@ class PhpParam {
|
||||
fbstring getDefault() const {
|
||||
return hasDefault() ? m_param["value"].asString() : "";
|
||||
}
|
||||
fbstring getDefaultSerialized() const;
|
||||
fbstring getDefaultPhp() const;
|
||||
|
||||
bool isCheckedType() const {
|
||||
return !isRef() && (kindOf() != KindOfAny);
|
||||
@@ -123,8 +199,10 @@ class PhpParam {
|
||||
private:
|
||||
fbstring m_name;
|
||||
folly::dynamic m_param;
|
||||
fbstring m_desc;
|
||||
DataType m_kindOf;
|
||||
fbstring m_cppType;
|
||||
fbstring m_phpType;
|
||||
};
|
||||
|
||||
class PhpFunc {
|
||||
@@ -133,6 +211,7 @@ class PhpFunc {
|
||||
|
||||
fbstring name() const { return m_name; }
|
||||
fbstring className() const { return m_className; }
|
||||
fbstring getDesc() const { return m_desc; }
|
||||
|
||||
bool isMethod() const {
|
||||
return !m_className.empty();
|
||||
@@ -169,6 +248,8 @@ class PhpFunc {
|
||||
bool isReturnRef() const { return m_returnRef; }
|
||||
DataType returnKindOf() const { return m_returnKindOf; }
|
||||
fbstring returnCppType() const { return m_returnCppType; }
|
||||
fbstring returnPhpType() const { return m_returnPhpType; }
|
||||
fbstring returnDesc() const { return m_returnDesc; }
|
||||
|
||||
bool isIndirectReturn() const { return isKindOfIndirect(returnKindOf()); }
|
||||
|
||||
@@ -176,6 +257,7 @@ class PhpFunc {
|
||||
bool isStatic() const { return m_flags & IsStatic; }
|
||||
bool isVarArgs() const { return m_flags & VarArgsMask; }
|
||||
bool usesThis() const { return isMethod() && !isStatic(); }
|
||||
unsigned int flags() const { return m_flags; }
|
||||
|
||||
int numParams() const { return m_params.size(); }
|
||||
int minNumParams() const { return m_minNumParams; }
|
||||
@@ -184,16 +266,27 @@ class PhpFunc {
|
||||
const PhpParam& param(int p) const { return m_params[p]; }
|
||||
const fbvector<PhpParam>& params() const { return m_params; }
|
||||
|
||||
bool hasDocComment() const {
|
||||
auto it = m_func.find("doc");
|
||||
return (it != m_func.items().end()) && it->second.size();
|
||||
}
|
||||
fbstring docComment() const {
|
||||
return hasDocComment() ? m_func["doc"].asString() : "";
|
||||
}
|
||||
|
||||
private:
|
||||
fbstring m_name;
|
||||
fbstring m_className;
|
||||
folly::dynamic m_func;
|
||||
unsigned long m_flags;
|
||||
fbstring m_desc;
|
||||
|
||||
// Return value
|
||||
bool m_returnRef;
|
||||
DataType m_returnKindOf;
|
||||
fbstring m_returnCppType;
|
||||
fbstring m_returnPhpType;
|
||||
fbstring m_returnDesc;
|
||||
|
||||
fbvector<PhpParam> m_params;
|
||||
|
||||
@@ -202,30 +295,81 @@ private:
|
||||
int m_numTypeChecks;
|
||||
};
|
||||
|
||||
class PhpProp {
|
||||
public:
|
||||
PhpProp(const folly::dynamic& d, fbstring cls);
|
||||
|
||||
fbstring name() const { return m_name; }
|
||||
fbstring className() const { return m_className; }
|
||||
unsigned long flags() const { return m_flags; }
|
||||
DataType kindOf() const { return m_kindOf; }
|
||||
|
||||
private:
|
||||
fbstring m_name;
|
||||
fbstring m_className;
|
||||
folly::dynamic m_prop;
|
||||
unsigned long m_flags;
|
||||
DataType m_kindOf;
|
||||
};
|
||||
|
||||
class PhpClass {
|
||||
public:
|
||||
explicit PhpClass(const folly::dynamic &c);
|
||||
|
||||
fbstring name() const { return m_name; }
|
||||
fbstring parent() const {
|
||||
auto p = m_class.find("parent");
|
||||
if (p == m_class.items().end()) {
|
||||
return "";
|
||||
}
|
||||
assert(p->second.isString());
|
||||
return p->second.asString();
|
||||
}
|
||||
|
||||
int numIfaces() const { return m_ifaces.size(); }
|
||||
fbvector<fbstring> ifaces() const { return m_ifaces; }
|
||||
|
||||
bool hasDocComment() const {
|
||||
auto it = m_class.find("doc");
|
||||
return (it != m_class.items().end()) && it->second.size();
|
||||
}
|
||||
fbstring docComment() const {
|
||||
return hasDocComment() ? m_class["doc"].asString() : "";
|
||||
}
|
||||
|
||||
fbstring getDesc() const { return m_desc; }
|
||||
|
||||
int numMethods() const { return m_methods.size(); }
|
||||
const fbvector<PhpFunc>& methods() const { return m_methods; }
|
||||
|
||||
unsigned long flags() const { return m_flags; }
|
||||
|
||||
int numProperties() const { return m_properties.size(); }
|
||||
fbvector<PhpProp> properties() const { return m_properties; }
|
||||
|
||||
int numConstants() const { return m_constants.size(); }
|
||||
fbvector<PhpConst> constants() const { return m_constants; }
|
||||
|
||||
private:
|
||||
folly::dynamic m_class;
|
||||
fbstring m_name;
|
||||
fbvector<fbstring> m_ifaces;
|
||||
fbvector<PhpFunc> m_methods;
|
||||
fbvector<PhpConst> m_constants;
|
||||
fbvector<PhpProp> m_properties;
|
||||
unsigned long m_flags;
|
||||
|
||||
void initFlagsProperty();
|
||||
fbstring m_desc;
|
||||
};
|
||||
|
||||
void parseIDL(const char* idlFilePath,
|
||||
fbvector<PhpFunc>& funcVec,
|
||||
fbvector<PhpClass>& classVec);
|
||||
|
||||
void parseIDL(const char* idlFilePath,
|
||||
fbvector<PhpFunc>& funcVec,
|
||||
fbvector<PhpClass>& classVec,
|
||||
fbvector<PhpConst>& constVec);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
}} // namespace HPHP::IDL
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,6 @@ HPHP_TOOLS=$HPHP_HOME/hphp/tools/
|
||||
if [ "$1" = "help" ]; then
|
||||
echo "$0 systemlib - Build bin/systemlib.php"
|
||||
echo "$0 constants - Build hphp/system/constants.h"
|
||||
echo "$0 class_map - Build hphp/system/class_map.cpp"
|
||||
echo "$0 lexer - Regenerate the lexer"
|
||||
echo "$0 parser - Regenerate the parser"
|
||||
echo "$0 license - Add license headers to all files"
|
||||
@@ -50,13 +49,6 @@ if [ "$1" = "constants" -o "$1" = "all" ]; then
|
||||
$HHVM hphp/idl/class_map.php hphp/system/constants.h hphp/system/globals/constdef.json
|
||||
fi
|
||||
|
||||
if [ "$1" = "class_map" -o "$1" = "all" ]; then
|
||||
cd $HPHP_HOME
|
||||
[ $VERBOSE -eq 1 ] && echo "Generating hphp/system/class_map.h"
|
||||
$HHVM hphp/idl/class_map.php hphp/system/class_map.cpp hphp/system/globals/constdef.json \
|
||||
`find hphp/idl -name '*.idl.json'`
|
||||
fi
|
||||
|
||||
if [ "$1" = "lexer" -o "$1" = "all" ]; then
|
||||
cd $HPHP_HOME/hphp/util/parser
|
||||
[ $VERBOSE -eq 1 ] && echo "Generating lexer"
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário