Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lexer and parser generator script #28

Open
wants to merge 14 commits into
base: PHP-8.3
Choose a base branch
from
Open
1 change: 0 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ jobs:
run: |
sudo apt-get -y install \
build-essential \
bison \
libssl-dev \
libpcre2-dev \
libsqlite3-dev \
Expand Down
102 changes: 2 additions & 100 deletions cmake/Zend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -523,108 +523,10 @@ if(TARGET Zend::MaxExecutionTimers)
endif()

################################################################################
# Generate lexers and parsers.
# Generate lexer and parser files.
################################################################################

if(BISON_FOUND)
bison_target(
zend_ini_parser
zend_ini_parser.y
${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_parser.c
COMPILE_FLAGS "${PHP_DEFAULT_BISON_FLAGS}"
VERBOSE REPORT_FILE zend_ini_parser.output
DEFINES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_parser.h
)

add_custom_target(zend_ini_parser DEPENDS ${BISON_TARGET_outputs})
add_dependencies(php_generate_files zend_ini_parser)

bison_target(
zend_language_parser
zend_language_parser.y
${CMAKE_CURRENT_SOURCE_DIR}/zend_language_parser.c
COMPILE_FLAGS "${PHP_DEFAULT_BISON_FLAGS}"
VERBOSE REPORT_FILE zend_language_parser.output
DEFINES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/zend_language_parser.h
)

# Tweak zendparse to be exported through ZEND_API. This has to be revisited
# once bison supports foreign skeletons and that bison version is used. Read
# https://git.savannah.gnu.org/cgit/bison.git/tree/data/README.md for more.
file(
GENERATE
OUTPUT CMakeFiles/PatchLanguageParser.cmake
CONTENT [[
file(READ "${SOURCE_DIR}/zend_language_parser.h" content)
string(
REPLACE
"int zendparse"
"ZEND_API int zendparse"
content_2
"${content}"
)
if(
NOT content MATCHES "ZEND_API int zendparse"
AND NOT content STREQUAL "${content_2}"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --blue --bold
" [Zend] Patching Zend/zend_language_parser.h"
)
file(WRITE "${SOURCE_DIR}/zend_language_parser.h" "${content_2}")
endif()

file(READ "${SOURCE_DIR}/zend_language_parser.c" content)
string(
REPLACE
"int zendparse"
"ZEND_API int zendparse"
content_2
"${content}"
)
if(
NOT content MATCHES "ZEND_API int zendparse"
AND NOT content STREQUAL "${content_2}"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --blue --bold
" [Zend] Patching Zend/zend_language_parser.c"
)
file(WRITE "${SOURCE_DIR}/zend_language_parser.c" "${content_2}")
endif()
]]
)

add_custom_target(
zend_patch_language_parser
COMMAND ${CMAKE_COMMAND}
-D SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-P "CMakeFiles/PatchLanguageParser.cmake"
DEPENDS ${BISON_zend_language_parser_OUTPUTS}
VERBATIM
)

add_dependencies(zend zend_patch_language_parser)
add_dependencies(php_generate_files zend_patch_language_parser)
endif()

if(RE2C_FOUND)
re2c_target(
zend_language_scanner
zend_language_scanner.l
${CMAKE_CURRENT_SOURCE_DIR}/zend_language_scanner.c
HEADER ${CMAKE_CURRENT_SOURCE_DIR}/zend_language_scanner_defs.h
OPTIONS --case-inverted -cbdF
)

re2c_target(
zend_ini_scanner
zend_ini_scanner.l
${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_scanner.c
HEADER ${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_scanner_defs.h
OPTIONS --case-inverted -cbdF
)
endif()
include(cmake/GenerateGrammar.cmake)

################################################################################
# Configure fibers.
Expand Down
131 changes: 131 additions & 0 deletions cmake/Zend/cmake/GenerateGrammar.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Generate lexer and parser files.

if(CMAKE_SCRIPT_MODE_FILE STREQUAL CMAKE_CURRENT_LIST_FILE)
message(FATAL_ERROR "This file should be used with include().")
endif()

include(PHP/Bison)

if(CMAKE_SCRIPT_MODE_FILE)
set(verbose "")
else()
set(verbose VERBOSE)
endif()

php_bison(
zend_ini_parser
zend_ini_parser.y
${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_parser.c
HEADER
ADD_DEFAULT_OPTIONS
${verbose}
CODEGEN
)

php_bison(
zend_language_parser
zend_language_parser.y
${CMAKE_CURRENT_SOURCE_DIR}/zend_language_parser.c
HEADER
ADD_DEFAULT_OPTIONS
${verbose}
CODEGEN
)

# Tweak zendparse to be exported through ZEND_API. This has to be revisited
# once bison supports foreign skeletons and that bison version is used. Read
# https://git.savannah.gnu.org/cgit/bison.git/tree/data/README.md for more.
block()
string(
CONCAT patch
"cmake_path(SET SOURCE_DIR NORMALIZE ${CMAKE_CURRENT_SOURCE_DIR})\n"
[[
cmake_path(
RELATIVE_PATH
SOURCE_DIR
BASE_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE relativeDir
)
file(READ "${SOURCE_DIR}/zend_language_parser.h" content)
string(
REPLACE
"int zendparse"
"ZEND_API int zendparse"
content_2
"${content}"
)
if(
NOT content MATCHES "ZEND_API int zendparse"
AND NOT content STREQUAL "${content_2}"
)
message(STATUS "Patching ${relativeDir}/zend_language_parser.h")
file(WRITE "${SOURCE_DIR}/zend_language_parser.h" "${content_2}")
endif()

file(READ "${SOURCE_DIR}/zend_language_parser.c" content)
string(
REPLACE
"int zendparse"
"ZEND_API int zendparse"
content_2
"${content}"
)
if(
NOT content MATCHES "ZEND_API int zendparse"
AND NOT content STREQUAL "${content_2}"
)
message(STATUS "Patching ${relativeDir}/zend_language_parser.c")
file(WRITE "${SOURCE_DIR}/zend_language_parser.c" "${content_2}")
endif()
]])

# Run patch based on whether building or running inside a CMake script.
if(CMAKE_SCRIPT_MODE_FILE)
cmake_language(EVAL CODE "${patch}")
else()
file(
GENERATE
OUTPUT CMakeFiles/Zend/PatchLanguageParser.cmake
CONTENT "${patch}"
)
add_custom_target(
zend_language_parser_patch
COMMAND ${CMAKE_COMMAND} -P CMakeFiles/Zend/PatchLanguageParser.cmake
DEPENDS zend_language_parser
VERBATIM
)
add_dependencies(zend zend_language_parser_patch)
endif()
endblock()

include(PHP/Re2c)

php_re2c(
zend_ini_scanner
zend_ini_scanner.l
${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_scanner.c
HEADER ${CMAKE_CURRENT_SOURCE_DIR}/zend_ini_scanner_defs.h
ADD_DEFAULT_OPTIONS
OPTIONS
--bit-vectors
--case-inverted
--conditions
--debug-output
--flex-syntax
CODEGEN
)

php_re2c(
zend_language_scanner
zend_language_scanner.l
${CMAKE_CURRENT_SOURCE_DIR}/zend_language_scanner.c
HEADER ${CMAKE_CURRENT_SOURCE_DIR}/zend_language_scanner_defs.h
ADD_DEFAULT_OPTIONS
OPTIONS
--bit-vectors
--case-inverted
--conditions
--debug-output
--flex-syntax
CODEGEN
)
4 changes: 0 additions & 4 deletions cmake/cmake/Bootstrap.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ add_library(php_sapi INTERFACE)
add_library(PHP::sapi ALIAS php_sapi)
target_link_libraries(php_sapi INTERFACE PHP::config)

# Create a custom target for generating files (parsers, lexers, etc.) manually:
# cmake --build <dir> -t php_generate_files
add_custom_target(php_generate_files)

# Configure build types.
include(cmake/BuildTypes.cmake)

Expand Down
13 changes: 3 additions & 10 deletions cmake/cmake/Configuration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ mark_as_advanced(PHP_PROGRAM_PREFIX)
set(PHP_PROGRAM_SUFFIX "" CACHE STRING "Append suffix to the program names")
mark_as_advanced(PHP_PROGRAM_SUFFIX)

option(PHP_RE2C_CGOTO "Enable computed goto GCC extension with re2c")
mark_as_advanced(PHP_RE2C_CGOTO)

option(PHP_THREAD_SAFETY "Enable thread safety (ZTS)")

cmake_dependent_option(
Expand Down Expand Up @@ -213,13 +210,6 @@ set(PHP_ZLIB_MIN_VERSION 1.2.0.4)
set(PHP_BZIP2_MIN_VERSION 1.0.0)

# Additional metadata for external packages to avoid duplication.
set_package_properties(
BISON
PROPERTIES
URL "https://www.gnu.org/software/bison/"
DESCRIPTION "General-purpose parser generator"
)

set_package_properties(
BZip2
PROPERTIES
Expand Down Expand Up @@ -268,3 +258,6 @@ set_package_properties(
URL "https://zlib.net/"
DESCRIPTION "Compression library"
)

# Set base directory for the ExternalProject CMake module across the PHP.
set_directory_properties(PROPERTIES EP_BASE ${PHP_BINARY_DIR}/_deps/EP)
72 changes: 0 additions & 72 deletions cmake/cmake/Requirements.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ include_guard(GLOBAL)

include(CheckSourceRuns)
include(CMakePushCheckState)
include(FeatureSummary)

################################################################################
# Check whether some minimum supported compiler is used.
Expand Down Expand Up @@ -45,77 +44,6 @@ else()
message(CHECK_PASS "ASCII")
endif()

################################################################################
# Check if bison and re2c are required.
#
# PHP tarball packaged and released at php.net already contains generated lexer
# and parser files. In such cases these don't need to be generated again. When
# building from a Git repository, bison and re2c are required to be installed so
# files can be generated as part of the build process.
################################################################################
#
# Check if bison is required.
if(
NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_ini_parser.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_ini_parser.h
OR NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_language_parser.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_language_parser.h
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/json/json_parser.tab.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/json/json_parser.tab.h
OR NOT EXISTS ${PHP_SOURCE_DIR}/sapi/phpdbg/phpdbg_parser.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/sapi/phpdbg/phpdbg_parser.h
)
find_package(BISON 3.0.0)
set_package_properties(
BISON
PROPERTIES
TYPE REQUIRED
PURPOSE "Necessary to generate PHP parser files."
)
# Add Bison options based on the build type.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.32)
# See: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/9921
set(PHP_DEFAULT_BISON_FLAGS "-Wall $<$<CONFIG:Release,MinSizeRel>:-l>")
else()
set(PHP_DEFAULT_BISON_FLAGS "$<IF:$<CONFIG:Release,MinSizeRel>,-lWall,-Wall>")
endif()
endif()

# Check if re2c is required.
if(
NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_language_scanner.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_language_scanner_defs.h
OR NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_ini_scanner.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/Zend/zend_ini_scanner_defs.h
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/json/json_scanner.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/json/php_json_scanner_defs.h
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/pdo/pdo_sql_parser.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/phar/phar_path_check.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/standard/url_scanner_ex.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/ext/standard/var_unserializer.c
OR NOT EXISTS ${PHP_SOURCE_DIR}/sapi/phpdbg/phpdbg_lexer.c
)
if(PHP_RE2C_CGOTO)
set(RE2C_USE_COMPUTED_GOTOS TRUE)
endif()

set(
RE2C_DEFAULT_OPTIONS
--no-generation-date # Suppress date output in the generated file.
$<$<CONFIG:Release,MinSizeRel>:-i> # Do not output line directives.
)

find_package(RE2C 1.0.3)
set_package_properties(
RE2C
PROPERTIES
TYPE REQUIRED
PURPOSE "Necessary to generate PHP lexer files."
)

add_dependencies(php_generate_files re2c_generate_files)
endif()

################################################################################
# Find mailer.
################################################################################
Expand Down
Loading
Loading