Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
#.rst:
|
||||
# FindLibIntl
|
||||
# ---------
|
||||
#
|
||||
# Find libintl
|
||||
#
|
||||
# Find the libintl headers and libraries. On platforms that use glibc this is not required
|
||||
# and LibIntl_LIBRARIES will be empty
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# LibIntl_INCLUDE_DIRS - where to find libintl.h
|
||||
# LibIntl_LIBRARIES - The libintl library if the current platform does not use glibc.
|
||||
# LibIntl_FOUND - True if libintl was found.
|
||||
|
||||
#=============================================================================
|
||||
# SPDX-FileCopyrightText: 2014 Alex Richardson <arichardson.kde@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#=============================================================================
|
||||
|
||||
find_path(LibIntl_INCLUDE_DIRS NAMES libintl.h)
|
||||
find_library(LibIntl_LIBRARIES NAMES intl libintl)
|
||||
|
||||
include(CheckCXXSymbolExists)
|
||||
include(CMakePushCheckState)
|
||||
check_cxx_symbol_exists(dngettext libintl.h LibIntl_SYMBOL_FOUND)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if(LibIntl_SYMBOL_FOUND)
|
||||
message(STATUS "libintl is part of libc, no extra library is required.")
|
||||
set(LibIntl_LIBRARIES "")
|
||||
if(LibIntl_INCLUDE_DIRS)
|
||||
find_package_handle_standard_args(LibIntl REQUIRED_VARS LibIntl_INCLUDE_DIRS)
|
||||
else()
|
||||
# in the default search path but not found by find_path, e.g. host glibc when cross-compiling
|
||||
set(LibIntl_INCLUDE_DIRS "")
|
||||
set(LibIntl_FOUND TRUE)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "libintl is a separate library.")
|
||||
find_package_handle_standard_args(LibIntl REQUIRED_VARS LibIntl_INCLUDE_DIRS LibIntl_LIBRARIES)
|
||||
endif()
|
||||
|
||||
# make sure we have -Wl,--no-undefined here, otherwise this test will always pass
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${LibIntl_LIBRARIES} ${CMAKE_SHARED_LINKER_FLAGS})
|
||||
check_cxx_source_compiles("extern \"C\" int _nl_msg_cat_cntr; int main(void) { ++_nl_msg_cat_cntr; return 0; }" HAVE_NL_MSG_CAT_CNTR)
|
||||
cmake_pop_check_state()
|
||||
@@ -0,0 +1,169 @@
|
||||
# SPDX-FileCopyrightText: 2006 Alexander Neundorf <neundorf@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
find_package(Gettext REQUIRED)
|
||||
|
||||
# The Python executable used for building ki18n will be used as a fallback
|
||||
# solution if it cannot be found in $PATH when building applications.
|
||||
find_program(KI18N_PYTHON_EXECUTABLE NAMES python3 python2 python)
|
||||
if(NOT KI18N_PYTHON_EXECUTABLE)
|
||||
set(KI18N_PYTHON_EXECUTABLE "@FALLBACK_KI18N_PYTHON_EXECUTABLE@")
|
||||
endif()
|
||||
|
||||
set(_ki18n_pmap_compile_script ${CMAKE_CURRENT_LIST_DIR}/ts-pmap-compile.py)
|
||||
set(_ki18n_uic_script ${CMAKE_CURRENT_LIST_DIR}/kf6i18nuic.cmake)
|
||||
set(_ki18n_build_pofiles_script ${CMAKE_CURRENT_LIST_DIR}/build-pofiles.cmake)
|
||||
set(_ki18n_build_tsfiles_script ${CMAKE_CURRENT_LIST_DIR}/build-tsfiles.cmake)
|
||||
|
||||
# Creates the implementation files from the ui files and adds them to the list of sources,
|
||||
# either to the variable of the given name or, since KF 5.62, if the given argument is
|
||||
# a target (must not be an alias), to the list of private sources of that target.
|
||||
#
|
||||
# ki18n_wrap_ui(<sources_var_name(|target (since 5.62))>
|
||||
# [<ui_file> [...]]
|
||||
# )
|
||||
#
|
||||
# Example usages:
|
||||
#
|
||||
# ki18n_wrap_ui(foo_SRCS ${ui_files})
|
||||
# ki18n_wrap_ui(foo ${ui_files})
|
||||
#
|
||||
macro (KI18N_WRAP_UI _sources )
|
||||
if(NOT TARGET Qt6::uic)
|
||||
message(FATAL_ERROR "Qt6Widgets should be found before calling ki18n_wrap_ui(). Please add find_package(Qt6Widgets ...)")
|
||||
endif()
|
||||
if (TARGET ${_sources})
|
||||
get_target_property(aliased_target ${_sources} ALIASED_TARGET)
|
||||
if(aliased_target)
|
||||
message(FATAL_ERROR "Target argument passed to ki18n_wrap_ui must not be an alias: ${_sources}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach (_current_FILE ${ARGN})
|
||||
|
||||
get_filename_component(_tmp_FILE ${_current_FILE} ABSOLUTE)
|
||||
if(NOT EXISTS ${_tmp_FILE})
|
||||
message(SEND_ERROR
|
||||
" Cannot find ui file:\n \n"
|
||||
" ${_current_FILE}\n")
|
||||
endif()
|
||||
get_filename_component(_basename ${_tmp_FILE} NAME_WE)
|
||||
set(_header ${CMAKE_CURRENT_BINARY_DIR}/ui_${_basename}.h)
|
||||
|
||||
get_target_property(QT_UIC_EXECUTABLE Qt6::uic LOCATION)
|
||||
# we need to run uic and replace some things in the generated file
|
||||
# this is done by executing the cmake script kf6i18nuic.cmake
|
||||
add_custom_command(OUTPUT ${_header}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
-DKDE_UIC_EXECUTABLE:FILEPATH=${QT_UIC_EXECUTABLE}
|
||||
-DKDE_UIC_FILE:FILEPATH=${_tmp_FILE}
|
||||
-DKDE_UIC_H_FILE:FILEPATH=${_header}
|
||||
-DKDE_UIC_BASENAME:STRING=${_basename}
|
||||
-P ${_ki18n_uic_script}
|
||||
MAIN_DEPENDENCY ${_tmp_FILE}
|
||||
)
|
||||
set_source_files_properties(${_tmp_FILE} PROPERTIES SKIP_AUTOUIC ON)
|
||||
set_source_files_properties(${_header} PROPERTIES SKIP_AUTOMOC ON)
|
||||
set_source_files_properties(${_header} PROPERTIES SKIP_AUTOUIC ON)
|
||||
if(TARGET ${_sources})
|
||||
target_sources(${_sources} PRIVATE ${_header})
|
||||
else()
|
||||
list(APPEND ${_sources} ${_header})
|
||||
endif()
|
||||
endforeach (_current_FILE)
|
||||
endmacro (KI18N_WRAP_UI)
|
||||
|
||||
option(KF_SKIP_PO_PROCESSING "Skip processing of po files" OFF)
|
||||
|
||||
# KI18N_INSTALL(podir)
|
||||
# Search for .po files and scripting modules and install them to the standard
|
||||
# location. The instalation can be skipped using the KF_SKIP_PO_PROCESSING option.
|
||||
#
|
||||
# This is a convenience function which relies on the following directory
|
||||
# structure:
|
||||
#
|
||||
# <podir>/
|
||||
# <lang>/
|
||||
# scripts/
|
||||
# <domain>/
|
||||
# *.js
|
||||
# *.po
|
||||
#
|
||||
# .po files are passed to build-pofiles.cmake
|
||||
#
|
||||
# .js files are installed using build-tsfiles.cmake
|
||||
#
|
||||
# For example, given the following directory structure:
|
||||
#
|
||||
# po/
|
||||
# fr/
|
||||
# scripts/
|
||||
# kfoo/
|
||||
# kfoo.js
|
||||
# kfoo.po
|
||||
#
|
||||
# KI18N_INSTALL(po) does the following:
|
||||
# - Compiles kfoo.po into kfoo.mo and installs it in
|
||||
# ${KDE_INSTALL_LOCALEDIR}/fr/LC_MESSAGES or share/locale/fr/LC_MESSAGES if
|
||||
# ${KDE_INSTALL_LOCALEDIR} is not set.
|
||||
# - Installs kfoo.js in ${KDE_INSTALL_LOCALEDIR}/fr/LC_SCRIPTS/kfoo
|
||||
#
|
||||
function(KI18N_INSTALL podir)
|
||||
if (KF_SKIP_PO_PROCESSING)
|
||||
return()
|
||||
endif()
|
||||
if (NOT KDE_INSTALL_LOCALEDIR)
|
||||
set(KDE_INSTALL_LOCALEDIR share/locale)
|
||||
endif()
|
||||
|
||||
# First try to find the po directory in the source directory, where the release scripts copy them before making the tarballs
|
||||
get_filename_component(absolute_podir ${podir} ABSOLUTE)
|
||||
|
||||
# we try to find the po directory in the binary directory, in case it was downloaded
|
||||
# using ECM
|
||||
if (NOT (EXISTS "${absolute_podir}" AND IS_DIRECTORY "${absolute_podir}"))
|
||||
get_filename_component(absolute_podir ${CMAKE_CURRENT_BINARY_DIR}/${podir} ABSOLUTE)
|
||||
endif()
|
||||
|
||||
if (NOT (EXISTS "${absolute_podir}" AND IS_DIRECTORY "${absolute_podir}"))
|
||||
# Nothing to do if there's no podir and it would create an empty
|
||||
# KDE_INSTALL_LOCALEDIR in that case.
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_filename_component(dirname ${KDE_INSTALL_LOCALEDIR} NAME)
|
||||
get_filename_component(destname ${KDE_INSTALL_LOCALEDIR} DIRECTORY)
|
||||
string(MD5 pathmd5 ${absolute_podir})
|
||||
|
||||
add_custom_target(pofiles-${pathmd5} ALL
|
||||
COMMENT "Generating mo..."
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DGETTEXT_MSGFMT_EXECUTABLE=${GETTEXT_MSGFMT_EXECUTABLE}
|
||||
-DCOPY_TO=${CMAKE_CURRENT_BINARY_DIR}/${dirname}
|
||||
-DPO_DIR=${absolute_podir}
|
||||
-P ${_ki18n_build_pofiles_script}
|
||||
)
|
||||
add_custom_target(tsfiles-${pathmd5} ALL
|
||||
COMMENT "Generating ts..."
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DPython3_EXECUTABLE=${KI18N_PYTHON_EXECUTABLE}
|
||||
-D_ki18n_pmap_compile_script=${_ki18n_pmap_compile_script}
|
||||
-DCOPY_TO=${CMAKE_CURRENT_BINARY_DIR}/${dirname}
|
||||
-DPO_DIR=${absolute_podir}
|
||||
-P ${_ki18n_build_tsfiles_script}
|
||||
)
|
||||
|
||||
if (NOT TARGET pofiles)
|
||||
add_custom_target(pofiles)
|
||||
endif()
|
||||
if (NOT TARGET tsfiles)
|
||||
add_custom_target(tsfiles)
|
||||
endif()
|
||||
add_dependencies(pofiles pofiles-${pathmd5})
|
||||
add_dependencies(tsfiles tsfiles-${pathmd5})
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dirname})
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dirname} DESTINATION ${destname})
|
||||
endfunction()
|
||||
@@ -0,0 +1,51 @@
|
||||
# SPDX-FileCopyrightText: 2017 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
# SPDX-FileCopyrightText: 2017 Harald Sitter <sitter@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
file(GLOB_RECURSE pofiles RELATIVE "${PO_DIR}" "${PO_DIR}/**.po")
|
||||
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(numberOfProcesses)
|
||||
|
||||
set(i 0)
|
||||
set(commands)
|
||||
|
||||
function(_processCommands)
|
||||
if(NOT commands)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
${commands}
|
||||
RESULT_VARIABLE code
|
||||
)
|
||||
if(code)
|
||||
message(FATAL_ERROR "failed generating ${PO_DIR}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
foreach(pofile IN LISTS pofiles)
|
||||
get_filename_component(name ${pofile} NAME)
|
||||
# Regex the basename, cmake only allows stripping the longest extension, we
|
||||
# need the shortest or we'll screw up "org.kde.plasma.kittens.po"
|
||||
# https://bugs.kde.org/show_bug.cgi?id=379116
|
||||
string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" name ${name})
|
||||
get_filename_component(langdir ${pofile} DIRECTORY)
|
||||
set(dest ${COPY_TO}/${langdir}/LC_MESSAGES)
|
||||
file(MAKE_DIRECTORY ${dest})
|
||||
|
||||
if (EXISTS ${dest}/${name}.mo AND ${dest}/${name}.mo IS_NEWER_THAN ${PO_DIR}/${pofile})
|
||||
continue()
|
||||
endif()
|
||||
|
||||
list(APPEND commands COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${dest}/${name}.mo ${PO_DIR}/${pofile})
|
||||
math(EXPR i "${i}+1")
|
||||
if(i EQUAL ${numberOfProcesses})
|
||||
_processCommands()
|
||||
set(i 0)
|
||||
set(commands)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
_processCommands()
|
||||
@@ -0,0 +1,65 @@
|
||||
# SPDX-FileCopyrightText: 2017 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
file(GLOB_RECURSE ts_files RELATIVE ${PO_DIR} ${PO_DIR}/**/scripts/*)
|
||||
foreach(ts_file ${ts_files})
|
||||
if(ts_file MATCHES "\\.svn")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
get_filename_component(subpath ${ts_file} DIRECTORY)
|
||||
string(REPLACE "scripts" "LC_SCRIPTS" subpath ${subpath})
|
||||
|
||||
message(STATUS "copying... ${PO_DIR}/${ts_file} DESTINATION ${COPY_TO}/${subpath}" )
|
||||
file(COPY ${PO_DIR}/${ts_file} DESTINATION ${COPY_TO}/${subpath})
|
||||
endforeach()
|
||||
|
||||
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(numberOfProcesses)
|
||||
|
||||
set(i 0)
|
||||
set(commands)
|
||||
|
||||
function(_processCommands)
|
||||
if(NOT commands)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
${commands}
|
||||
RESULT_VARIABLE code
|
||||
)
|
||||
if(code)
|
||||
message(FATAL_ERROR "failed generating: ${PO_DIR}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
file(GLOB_RECURSE pmap_files RELATIVE ${PO_DIR} "${PO_DIR}/**.pmap")
|
||||
foreach(pmap_file ${pmap_files})
|
||||
get_filename_component(pmap_basename ${pmap_file} NAME)
|
||||
get_filename_component(subpath ${pmap_file} DIRECTORY)
|
||||
string(REPLACE "scripts" "LC_SCRIPTS" subpath ${subpath})
|
||||
set(pmapc_file "${COPY_TO}/${subpath}/${pmap_basename}c")
|
||||
|
||||
if (EXISTS ${pmapc_file} AND ${pmapc_file} IS_NEWER_THAN ${pmap_file})
|
||||
continue()
|
||||
endif()
|
||||
|
||||
message(STATUS "building... ${pmap_file} to ${pmapc_file}" )
|
||||
list(APPEND commands
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
-B
|
||||
${_ki18n_pmap_compile_script}
|
||||
${PO_DIR}/${pmap_file}
|
||||
${pmapc_file}
|
||||
)
|
||||
math(EXPR i "${i}+1")
|
||||
if (i EQUAL ${numberOfProcesses})
|
||||
_processCommands()
|
||||
set(i 0)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
_processCommands()
|
||||
@@ -0,0 +1,26 @@
|
||||
# SPDX-FileCopyrightText: 2006 Alexander Neundorf <neundorf@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
EXECUTE_PROCESS(COMMAND ${KDE_UIC_EXECUTABLE}
|
||||
-tr tr2i18n
|
||||
${KDE_UIC_FILE}
|
||||
OUTPUT_VARIABLE _uic_CONTENTS
|
||||
)
|
||||
|
||||
set(KDE_UIC_CPP_FILE ${KDE_UIC_H_FILE})
|
||||
|
||||
|
||||
IF (_uic_CONTENTS)
|
||||
#replace tr218n("") with QString() to avoid warning from KLocale
|
||||
STRING(REGEX REPLACE "tr2i18n\\(\"\"\\)" "QString\(\)" _uic_CONTENTS "${_uic_CONTENTS}" )
|
||||
STRING(REGEX REPLACE "tr2i18n\\(\"\", \"\"\\)" "QString\(\)" _uic_CONTENTS "${_uic_CONTENTS}" )
|
||||
#replace image15_data with img15_filename to make enable_final work
|
||||
STRING(REGEX REPLACE "image([0-9]+)_data" "img\\1_${KDE_UIC_BASENAME}" _uic_CONTENTS "${_uic_CONTENTS}")
|
||||
#fixup include guard
|
||||
STRING(REGEX REPLACE "#ifndef " "#ifndef UI_" _uic_CONTENTS "${_uic_CONTENTS}")
|
||||
STRING(REGEX REPLACE "#define " "#define UI_" _uic_CONTENTS "${_uic_CONTENTS}")
|
||||
|
||||
FILE(WRITE ${KDE_UIC_CPP_FILE} "#include <klocalizedstring.h>\n\n${_uic_CONTENTS}\n")
|
||||
ENDIF()
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# Script that compiles Transcript property maps from text to binary format.
|
||||
# Binary format greately speeds up loading of property maps at runtime.
|
||||
# http://techbase.kde.org/Localization/Concepts/Transcript
|
||||
#
|
||||
# Usage:
|
||||
# ts-pmap-compile.py file.pmap file.pmapc
|
||||
#
|
||||
# Works with Python >= 2.6 and >= 3.0.
|
||||
|
||||
import locale
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
cmdname = os.path.basename(sys.argv[0])
|
||||
lenc = locale.getpreferredencoding()
|
||||
|
||||
def error (msg, code=1):
|
||||
sys.stderr.write(("%s: error: %s\n" % (cmdname, msg)).encode(lenc))
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
def count_lines (text, tolen):
|
||||
return text.count("\n", 0, tolen) + 1
|
||||
|
||||
|
||||
def norm_keystr (text):
|
||||
# Must do the same as normKeystr() in kdelibs/kdecore/ktranscript.cpp
|
||||
return re.sub("[\s&]", "", text).lower()
|
||||
|
||||
|
||||
def trim_smart (text):
|
||||
return re.sub("^\s*\n|\n\s*$", "", text)
|
||||
|
||||
|
||||
def read_pmap (fname):
|
||||
|
||||
# Adapted directly from C++ code.
|
||||
|
||||
fh = open(fname, "rb")
|
||||
s = "".join([l.decode("utf8") for l in fh.readlines()])
|
||||
fh.close()
|
||||
|
||||
s_nextEntry, s_nextKey, s_nextValue = 1, 2, 3
|
||||
|
||||
pmap = []
|
||||
|
||||
class END_PROP_PARSE (Exception): pass
|
||||
try:
|
||||
slen = len(s)
|
||||
state = s_nextEntry
|
||||
ekeys = [] # holds keys for current entry
|
||||
props = [] # holds properties for current entry
|
||||
pkey = "" # holds current property key
|
||||
i = 0
|
||||
while True:
|
||||
i_checkpoint = i
|
||||
|
||||
if state == s_nextEntry:
|
||||
while s[i].isspace():
|
||||
i += 1
|
||||
if i >= slen: raise END_PROP_PARSE
|
||||
|
||||
if i + 1 >= slen:
|
||||
error("unexpected end of file %s" % fname)
|
||||
|
||||
if s[i] != '#':
|
||||
# Separator characters for this entry.
|
||||
key_sep = s[i]
|
||||
prop_sep = s[i + 1]
|
||||
if key_sep.isalpha() or prop_sep.isalpha():
|
||||
error("separator characters must not be letters "
|
||||
"at %s:%d" % (fname, count_lines(s, i)))
|
||||
|
||||
# Reset all data for current entry.
|
||||
ekeys = []
|
||||
props = []
|
||||
pkey = ""
|
||||
|
||||
i += 2
|
||||
state = s_nextKey
|
||||
|
||||
else:
|
||||
# This is a comment, skip to EOL, don't change state.
|
||||
while s[i] != '\n':
|
||||
i += 1
|
||||
if i >= slen: raise END_PROP_PARSE
|
||||
|
||||
elif state == s_nextKey:
|
||||
ip = i
|
||||
# Proceed up to next key or property separator.
|
||||
while s[i] != key_sep and s[i] != prop_sep:
|
||||
i += 1
|
||||
if i >= slen: raise END_PROP_PARSE
|
||||
|
||||
if s[i] == key_sep:
|
||||
# This is a property key,
|
||||
# record for when the value gets parsed.
|
||||
pkey = norm_keystr(s[ip:i])
|
||||
|
||||
i += 1
|
||||
state = s_nextValue
|
||||
|
||||
else: # if (s[i] == prop_sep
|
||||
# This is an entry key, or end of entry.
|
||||
ekey = norm_keystr(s[ip:i])
|
||||
if ekey:
|
||||
# An entry key.
|
||||
ekeys.append(ekey)
|
||||
|
||||
i += 1
|
||||
state = s_nextKey
|
||||
|
||||
else:
|
||||
# End of entry.
|
||||
if len(ekeys) < 1:
|
||||
error("no entry key for entry ending "
|
||||
"at %s:%d" % (fname, count_lines(s, i)))
|
||||
|
||||
# Put collected properties into global store.
|
||||
pmap.append((ekeys, props))
|
||||
|
||||
i += 1
|
||||
state = s_nextEntry
|
||||
# This check covers no newline at end of file.
|
||||
if i >= slen: raise END_PROP_PARSE
|
||||
|
||||
elif state == s_nextValue:
|
||||
ip = i
|
||||
# Proceed up to next property separator.
|
||||
while s[i] != prop_sep:
|
||||
i += 1
|
||||
if i >= slen: raise END_PROP_PARSE
|
||||
if s[i] == key_sep:
|
||||
error("property separator inside property value "
|
||||
"at %s:%d" % (fname, count_lines(s, i)))
|
||||
|
||||
# Extract the property value and store the property.
|
||||
pval = trim_smart(s[ip:i])
|
||||
props.append((pkey, pval))
|
||||
|
||||
i += 1
|
||||
state = s_nextKey
|
||||
|
||||
else:
|
||||
error("internal error 10 "
|
||||
"at %s:%d" % (fname, count_lines(s, i)))
|
||||
|
||||
# To avoid infinite looping and stepping out.
|
||||
if i == i_checkpoint or i >= slen:
|
||||
error("internal error 20 "
|
||||
"at %s:%d" % (fname, count_lines(s, i)))
|
||||
|
||||
except END_PROP_PARSE:
|
||||
if state != s_nextEntry:
|
||||
error("unexpected end of file in %s" % fname)
|
||||
|
||||
return pmap
|
||||
|
||||
|
||||
# Convert integer to 32-bit big-endian byte sequence.
|
||||
def int_bin_32 (val):
|
||||
return struct.pack(">i", val)[-4:]
|
||||
|
||||
|
||||
# Convert integer to 64-bit big-endian byte sequence.
|
||||
def int_bin_64 (val):
|
||||
return struct.pack(">q", val)[-8:]
|
||||
|
||||
|
||||
# Convert string to UTF-8 byte sequence,
|
||||
# preceded by its length in 32-bit big-endian.
|
||||
def str_bin_32 (val):
|
||||
val_enc = val.encode("utf8")
|
||||
return int_bin_32(len(val_enc)) + val_enc
|
||||
|
||||
|
||||
# Concatenate byte sequence.
|
||||
def catb (seq):
|
||||
return bytes().join(seq)
|
||||
|
||||
|
||||
# Binary map format 00.
|
||||
def write_map_bin_00 (fh, pmap):
|
||||
|
||||
# Magic bytes.
|
||||
fh.write("TSPMAP00".encode("ascii"))
|
||||
|
||||
# Number of entries.
|
||||
fh.write(int_bin_32(len(pmap)))
|
||||
|
||||
for ekeys, props in pmap:
|
||||
# Number of phrase keys and all phrase keys.
|
||||
fh.write(int_bin_32(len(ekeys)))
|
||||
for ekey in ekeys:
|
||||
fh.write(str_bin_32(ekey))
|
||||
|
||||
# Number of properties and all properties.
|
||||
fh.write(int_bin_32(len(props)))
|
||||
for pkey, pval in props:
|
||||
fh.write(str_bin_32(pkey))
|
||||
fh.write(str_bin_32(pval))
|
||||
|
||||
|
||||
# Binary map format 01.
|
||||
def write_map_bin_01 (fh, pmap):
|
||||
|
||||
offset0 = 0
|
||||
binint32len = len(int_bin_32(0))
|
||||
binint64len = len(int_bin_64(0))
|
||||
|
||||
# Magic bytes.
|
||||
mbytestr = "TSPMAP01".encode("ascii")
|
||||
offset0 += len(mbytestr)
|
||||
|
||||
# Compute length of binary representation of all entry keys
|
||||
# additionally equipped with offsets to corresponding property blobs.
|
||||
offset0 += binint32len
|
||||
offset0 += binint64len
|
||||
binekeyslen = 0
|
||||
for ekeys, d1 in pmap:
|
||||
binekeyslen += sum([len(str_bin_32(x)) + binint64len for x in ekeys])
|
||||
offset0 += binekeyslen
|
||||
|
||||
# Construct binary representations of all unique property keys.
|
||||
offset0 += binint32len
|
||||
offset0 += binint64len
|
||||
allpkeys = set()
|
||||
for d1, props in pmap:
|
||||
allpkeys.update([x[0] for x in props])
|
||||
binpkeys = catb(map(str_bin_32, sorted(allpkeys)))
|
||||
offset0 += len(binpkeys)
|
||||
|
||||
# Construct binary representations of properties for each entry.
|
||||
# Compute byte offsets for each of these binary blobs, in the given order.
|
||||
binprops = []
|
||||
plength = 0
|
||||
poffset = offset0 + binint32len
|
||||
for d1, props in pmap:
|
||||
cbinprops = catb(sum([list(map(str_bin_32, x)) for x in props], []))
|
||||
cbinprops = catb([int_bin_32(len(props)), int_bin_32(len(cbinprops)),
|
||||
cbinprops])
|
||||
offset = poffset + plength
|
||||
binprops.append([cbinprops, offset])
|
||||
poffset = offset
|
||||
plength = len(cbinprops)
|
||||
|
||||
# Construct binary representations of all entry keys with property offsets.
|
||||
allekeys = []
|
||||
binekeys = []
|
||||
for (ekeys, d1), (d2, offset) in zip(pmap, binprops):
|
||||
binoffset = int_bin_64(offset)
|
||||
cbinekeys = catb([str_bin_32(x) + binoffset for x in ekeys])
|
||||
binekeys.append(cbinekeys)
|
||||
allekeys.extend(ekeys)
|
||||
binekeys = catb(binekeys)
|
||||
assert(binekeyslen == len(binekeys))
|
||||
|
||||
# Write everything out.
|
||||
fh.write(mbytestr)
|
||||
fh.write(int_bin_32(len(allekeys)))
|
||||
fh.write(int_bin_64(len(binekeys)))
|
||||
fh.write(binekeys)
|
||||
fh.write(int_bin_32(len(allpkeys)))
|
||||
fh.write(int_bin_64(len(binpkeys)))
|
||||
fh.write(binpkeys)
|
||||
fh.write(int_bin_32(len(pmap)))
|
||||
for cbinprops, d1 in binprops:
|
||||
fh.write(cbinprops)
|
||||
|
||||
|
||||
def main ():
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
error("usage: %s INPUT_FILE OUTPUT_FILE" % cmdname)
|
||||
|
||||
try:
|
||||
import psyco
|
||||
psyco.full()
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
ifile = sys.argv[1]
|
||||
ofile = sys.argv[2]
|
||||
|
||||
pmap = read_pmap(ifile)
|
||||
ofh = open(ofile, "wb")
|
||||
write_map_bin_01(ofh, pmap)
|
||||
ofh.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user