mirror of
https://github.com/servo/servo.git
synced 2025-06-29 11:33:39 +01:00
Specifically: - nsICSSAnonBoxPseudo --> nsCSSAnonBoxPseudoStaticAtom - nsICSSPseudoElement --> nsCSSPseudoElementStaticAtom The `nsI` prefix isn't necessary because these are no longer XPIDL types, and the `StaticAtom` suffix makes their meaning clearer. Bug: 1497734 Reviewed-by: heycam
230 lines
6.8 KiB
Python
Executable file
230 lines
6.8 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
import re
|
|
import os
|
|
import sys
|
|
|
|
from io import BytesIO
|
|
|
|
GECKO_DIR = os.path.dirname(__file__.replace('\\', '/'))
|
|
sys.path.insert(0, os.path.join(os.path.dirname(GECKO_DIR), "properties"))
|
|
|
|
import build
|
|
|
|
|
|
# Matches lines like `GK_ATOM(foo, "foo", 0x12345678, nsStaticAtom, PseudoElementAtom)`.
|
|
PATTERN = re.compile('^GK_ATOM\(([^,]*),[^"]*"([^"]*)",\s*(0x[0-9a-f]+),\s*([^,]*),\s*([^)]*)\)',
|
|
re.MULTILINE)
|
|
FILE = "include/nsGkAtomList.h"
|
|
|
|
|
|
def map_atom(ident):
|
|
if ident in {"box", "loop", "match", "mod", "ref",
|
|
"self", "type", "use", "where", "in"}:
|
|
return ident + "_"
|
|
return ident
|
|
|
|
|
|
class Atom:
|
|
def __init__(self, ident, value, hash, ty, atom_type):
|
|
self.ident = "nsGkAtoms_{}".format(ident)
|
|
self.original_ident = ident
|
|
self.value = value
|
|
self.hash = hash
|
|
# The Gecko type: "nsStaticAtom", "nsCSSPseudoElementStaticAtom", or
|
|
# "nsAnonBoxPseudoStaticAtom".
|
|
self.ty = ty
|
|
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
|
|
# or "InheritingAnonBox".
|
|
self.atom_type = atom_type
|
|
if self.is_pseudo() or self.is_anon_box():
|
|
self.pseudo_ident = (ident.split("_", 1))[1]
|
|
if self.is_anon_box():
|
|
assert self.is_inheriting_anon_box() or self.is_non_inheriting_anon_box()
|
|
|
|
def type(self):
|
|
return self.ty
|
|
|
|
def capitalized_pseudo(self):
|
|
return self.pseudo_ident[0].upper() + self.pseudo_ident[1:]
|
|
|
|
def is_pseudo(self):
|
|
return self.atom_type == "PseudoElementAtom"
|
|
|
|
def is_anon_box(self):
|
|
return self.is_non_inheriting_anon_box() or self.is_inheriting_anon_box()
|
|
|
|
def is_non_inheriting_anon_box(self):
|
|
return self.atom_type == "NonInheritingAnonBoxAtom"
|
|
|
|
def is_inheriting_anon_box(self):
|
|
return self.atom_type == "InheritingAnonBoxAtom"
|
|
|
|
def is_tree_pseudo_element(self):
|
|
return self.value.startswith(":-moz-tree-")
|
|
|
|
|
|
def collect_atoms(objdir):
|
|
atoms = []
|
|
path = os.path.abspath(os.path.join(objdir, FILE))
|
|
print("cargo:rerun-if-changed={}".format(path))
|
|
with open(path) as f:
|
|
content = f.read()
|
|
for result in PATTERN.finditer(content):
|
|
atoms.append(Atom(result.group(1), result.group(2), result.group(3),
|
|
result.group(4), result.group(5)))
|
|
return atoms
|
|
|
|
|
|
class FileAvoidWrite(BytesIO):
|
|
"""File-like object that buffers output and only writes if content changed."""
|
|
def __init__(self, filename):
|
|
BytesIO.__init__(self)
|
|
self.name = filename
|
|
|
|
def write(self, buf):
|
|
if isinstance(buf, unicode):
|
|
buf = buf.encode('utf-8')
|
|
BytesIO.write(self, buf)
|
|
|
|
def close(self):
|
|
buf = self.getvalue()
|
|
BytesIO.close(self)
|
|
try:
|
|
with open(self.name, 'rb') as f:
|
|
old_content = f.read()
|
|
if old_content == buf:
|
|
print("{} is not changed, skip".format(self.name))
|
|
return
|
|
except IOError:
|
|
pass
|
|
with open(self.name, 'wb') as f:
|
|
f.write(buf)
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
if not self.closed:
|
|
self.close()
|
|
|
|
|
|
PRELUDE = '''
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// Autogenerated file created by components/style/gecko/regen_atoms.py.
|
|
// DO NOT EDIT DIRECTLY
|
|
'''[1:]
|
|
|
|
IMPORTS = '''
|
|
use gecko_bindings::structs::nsStaticAtom;
|
|
use string_cache::Atom;
|
|
'''
|
|
|
|
UNSAFE_STATIC = '''
|
|
#[inline(always)]
|
|
pub unsafe fn atom_from_static(ptr: *const nsStaticAtom) -> Atom {
|
|
Atom::from_static(ptr)
|
|
}
|
|
'''
|
|
|
|
SATOMS_TEMPLATE = '''
|
|
#[link_name = \"{link_name}\"]
|
|
pub static nsGkAtoms_sAtoms: *const nsStaticAtom;
|
|
'''[1:]
|
|
|
|
CFG_IF_TEMPLATE = '''
|
|
cfg_if! {{
|
|
if #[cfg(not(target_env = "msvc"))] {{
|
|
extern {{
|
|
{gnu}\
|
|
}}
|
|
}} else if #[cfg(target_pointer_width = "64")] {{
|
|
extern {{
|
|
{msvc64}\
|
|
}}
|
|
}} else {{
|
|
extern {{
|
|
{msvc32}\
|
|
}}
|
|
}}
|
|
}}\n
|
|
'''
|
|
|
|
CONST_TEMPLATE = '''
|
|
pub const k_{name}: isize = {index};
|
|
'''[1:]
|
|
|
|
RULE_TEMPLATE = '''
|
|
("{atom}") =>
|
|
{{{{
|
|
use $crate::string_cache::atom_macro;
|
|
#[allow(unsafe_code)] #[allow(unused_unsafe)]
|
|
unsafe {{ atom_macro::atom_from_static(atom_macro::nsGkAtoms_sAtoms.offset(atom_macro::k_{name})) }}
|
|
}}}};
|
|
'''[1:]
|
|
|
|
MACRO_TEMPLATE = '''
|
|
#[macro_export]
|
|
macro_rules! atom {{
|
|
{body}\
|
|
}}
|
|
'''
|
|
|
|
def write_atom_macro(atoms, file_name):
|
|
with FileAvoidWrite(file_name) as f:
|
|
f.write(PRELUDE)
|
|
f.write(IMPORTS)
|
|
f.write(UNSAFE_STATIC)
|
|
|
|
gnu_name='_ZN9nsGkAtoms6sAtomsE'
|
|
gnu_symbols = SATOMS_TEMPLATE.format(link_name=gnu_name)
|
|
|
|
# Prepend "\x01" to avoid LLVM prefixing the mangled name with "_".
|
|
# See https://github.com/rust-lang/rust/issues/36097
|
|
msvc32_name = '\\x01?sAtoms@nsGkAtoms@@0QBVnsStaticAtom@@B'
|
|
msvc32_symbols = SATOMS_TEMPLATE.format(link_name=msvc32_name)
|
|
|
|
msvc64_name = '?sAtoms@nsGkAtoms@@0QEBVnsStaticAtom@@EB'
|
|
msvc64_symbols = SATOMS_TEMPLATE.format(link_name=msvc64_name)
|
|
|
|
f.write(CFG_IF_TEMPLATE.format(gnu=gnu_symbols, msvc32=msvc32_symbols, msvc64=msvc64_symbols))
|
|
|
|
consts = [CONST_TEMPLATE.format(name=atom.ident, index=i) for (i, atom) in enumerate(atoms)]
|
|
f.write('{}'.format(''.join(consts)))
|
|
|
|
macro_rules = [RULE_TEMPLATE.format(atom=atom.value, name=atom.ident) for atom in atoms]
|
|
f.write(MACRO_TEMPLATE.format(body=''.join(macro_rules)))
|
|
|
|
|
|
def write_pseudo_elements(atoms, target_filename):
|
|
pseudos = []
|
|
for atom in atoms:
|
|
if atom.type() == "nsCSSPseudoElementStaticAtom" or atom.type() == "nsCSSAnonBoxPseudoStaticAtom":
|
|
pseudos.append(atom)
|
|
|
|
pseudo_definition_template = os.path.join(GECKO_DIR, "pseudo_element_definition.mako.rs")
|
|
print("cargo:rerun-if-changed={}".format(pseudo_definition_template))
|
|
contents = build.render(pseudo_definition_template, PSEUDOS=pseudos)
|
|
|
|
with FileAvoidWrite(target_filename) as f:
|
|
f.write(contents)
|
|
|
|
|
|
def generate_atoms(dist, out):
|
|
atoms = collect_atoms(dist)
|
|
write_atom_macro(atoms, os.path.join(out, "atom_macro.rs"))
|
|
write_pseudo_elements(atoms, os.path.join(out, "pseudo_element_definition.rs"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 3:
|
|
print("Usage: {} dist out".format(sys.argv[0]))
|
|
exit(2)
|
|
generate_atoms(sys.argv[1], sys.argv[2])
|